王建東++張興堯++佟志臣++夏智
摘 要
本文提出了一種在高并發(fā)環(huán)境下交易日志連續(xù)輸出的機(jī)制。該方法能夠接受日志的并發(fā)無(wú)序提交,根據(jù)日志中交易的交易主鍵將日志進(jìn)行邏輯劃分,使得同一筆交易日志高度內(nèi)聚,保證了日志的連續(xù)輸出,大大提高了日志的可讀性和友好性,減少甚至避免了日志分析中對(duì)日志的額外處理。
【關(guān)鍵詞】交易日志 高并發(fā) 連續(xù)輸出
交易日志對(duì)現(xiàn)代交易系統(tǒng)具有極其重要的意義,其作用主要有三個(gè):?jiǎn)栴}排查、交易信息歸檔、交易分析與挖掘。交易日志完整記錄了每筆交易的具體執(zhí)行路徑。通過(guò)人工查看日志,可以精確把握一筆交易成功、失敗以及其他異常信息。目前,聯(lián)機(jī)交易系統(tǒng)在高并發(fā)環(huán)境下,日志的輸出通常是不連續(xù)的。一筆交易的日志中無(wú)規(guī)律地穿插著其他交易的日志信息,這樣在日志查閱、問(wèn)題排查時(shí)非常不便,需要在現(xiàn)有日志基礎(chǔ)上進(jìn)一步將一筆交易從眾多交易日志中隔離或抽取出來(lái)才能得到有效的日志信息。
1 系統(tǒng)原理
本文提出一種處理機(jī)制,在日志被輸出到目標(biāo)日志文件之前,在內(nèi)存緩沖區(qū)中對(duì)日志進(jìn)行分揀,并按照一定的策略或在一定的時(shí)機(jī)輸出日志,使得每筆交易日志高度內(nèi)聚,即使在高并發(fā)環(huán)境下亦不存在穿插的現(xiàn)象,同時(shí)保證單筆交易日志內(nèi)部有序。
工作原理如圖1所示。
按照標(biāo)號(hào),1)首先接收交易系統(tǒng)日志提交,2)將日志做持久化處理,3)然后將日志交由日志處理模塊進(jìn)行實(shí)時(shí)分揀,4)并按照一定的輸出策略進(jìn)行日志輸出,5)最后記錄日志快照。對(duì)于意外斷電或系統(tǒng)崩潰的情況,緩沖區(qū)內(nèi)的日志因沒(méi)能及時(shí)輸出而丟失。下次啟動(dòng)時(shí),分別讀取持久化日志和日志快照,經(jīng)日志恢復(fù)模塊處理后交給日志處理模塊,然后強(qiáng)制輸出此部分日志,清空持久化日志和日志快照,此后便可重新接受新日志的提交,此時(shí)系統(tǒng)恢復(fù)到正常的工作狀態(tài)。
2 實(shí)施方案
由于本方法需要在內(nèi)存緩沖區(qū)內(nèi)對(duì)每條日志進(jìn)行分揀,日志在被輸出到目標(biāo)文件之前是存放在內(nèi)存中的。而對(duì)于一個(gè)應(yīng)用來(lái)說(shuō),分配的內(nèi)存大小是有限的。為了防止因日志條目不斷增長(zhǎng)造成占用的內(nèi)存無(wú)限增加,日志系統(tǒng)設(shè)定一個(gè)參數(shù):超時(shí)時(shí)間timeout。超時(shí)時(shí)間控制一筆交易的輸出時(shí)機(jī),當(dāng)當(dāng)前時(shí)間與交易上次提交時(shí)間lasttime的間隔大于超時(shí)時(shí)間時(shí),此交易的日志被立即輸出。
對(duì)于一筆交易,其都有一個(gè)確定的交易主鍵tkey。對(duì)于一條交易日志,都有一個(gè)tkey與其關(guān)聯(lián)。若任何兩條交易日志的tkey相同,則認(rèn)為它們同屬一筆交易,應(yīng)被連續(xù)輸出。
以下對(duì)各個(gè)模塊詳細(xì)闡述。
2.1 日志提交
當(dāng)交易系統(tǒng)需要記錄日志時(shí),交易系統(tǒng)向日志系統(tǒng)同時(shí)提交tkey和與tkey相關(guān)的日志信息。具體分兩類(lèi)提交:
(1)類(lèi)提交:同時(shí)提交tkey和日志正文msg。
(2)類(lèi)提交:同時(shí)提交tkey和結(jié)束標(biāo)志finish。
若日志并非一筆交易的最后一條日志,則按交易流程將日志逐條進(jìn)行a類(lèi)提交,此步向日志系統(tǒng)提交日志正文msg。若一條日志是交易的最后一條日志,則對(duì)這條日志進(jìn)行a類(lèi)提交后,同時(shí)進(jìn)行b類(lèi)提交。此時(shí)的b類(lèi)提交不含日志正文,而是日志結(jié)束標(biāo)志finish。b類(lèi)提交出現(xiàn)在交易的出口處,通知日志系統(tǒng)一筆交易已結(jié)束。一筆交易可能因交易成功、交易失敗、系統(tǒng)異常等有多個(gè)交易出口,這些出口均需設(shè)置b類(lèi)提交。當(dāng)系統(tǒng)發(fā)生了嚴(yán)重錯(cuò)誤時(shí),b類(lèi)提交可能無(wú)法正常完成,此時(shí)由超時(shí)時(shí)間控制日志的輸出。
2.2 日志持久化
為了防止意外斷電或系統(tǒng)崩潰等原因?qū)е聝?nèi)存中的日志丟失,日志系統(tǒng)在接收到交易系統(tǒng)的日志提交后,首先將日志實(shí)時(shí)地、無(wú)序地寫(xiě)入磁盤(pán),確切的說(shuō),寫(xiě)入到持久化日志文件。日志系統(tǒng)維護(hù)一個(gè)持久化日志文件,日志以行存放,每行包含tkey和msg。持久化日志文件設(shè)定文件大小,采用循環(huán)覆蓋(rotate)的方式,具體文件大小可以根據(jù)交易系統(tǒng)情況而定。另外,對(duì)于日志實(shí)時(shí)性要求很高的情況,可以通過(guò)此文件查看在緩存中尚未及時(shí)輸出的日志。
2.3 日志處理
日志系統(tǒng)內(nèi)部維護(hù)一個(gè)自定義的數(shù)據(jù)結(jié)構(gòu)Ldata,保存tkey、lasttime和一個(gè)有序鏈表Llist。Llist的每一個(gè)節(jié)點(diǎn)存放一條日志正文。同時(shí)維護(hù)一個(gè)哈希表Lmap,Lmap以tkey為key,以L(fǎng)data為value,是交易在內(nèi)存中的清單。
日志處理模塊主要負(fù)責(zé)接收日志提交和日志輸出。當(dāng)接收到交易系統(tǒng)的提交的日志時(shí),日志處理模塊進(jìn)行判斷。若是a類(lèi)提交,則在Lmap中根據(jù)tkey查找對(duì)應(yīng)的Ldata,查找失敗則根據(jù)tkey創(chuàng)建Ldata并添加到Lmap中,表明這是一筆新的交易,此時(shí)Ldata中的lasttime為當(dāng)前時(shí)間,Llist中保存著這筆交易的第一條日志;查找成功則更新Ldata的lasttime為當(dāng)前時(shí)間,并將日志正文添加到Llist中;若是b類(lèi)提交,則按照提交順序依次輸出Llist中的日志,將tkey從Lmap中移除,并在快照文件中記錄相應(yīng)的tkey。
另外,對(duì)日志輸出進(jìn)行超時(shí)控制,必要時(shí)強(qiáng)制輸出交易日志。具體來(lái)講,遍歷Lmap,按tkey逐個(gè)取Ldata。判斷當(dāng)前時(shí)間與lasttime的差值,若差值大于timeout,則表明超時(shí)發(fā)生,立即輸出,否則取下一個(gè)Ldata。日志輸出后,將其對(duì)應(yīng)的tkey從Lmap中移除,并在快照文件中記錄。
2.4 日志快照
日志快照模塊維護(hù)一個(gè)日志快照文件,記錄已順利輸出的交易的tkey。日志快照文件類(lèi)似于NOSQL數(shù)據(jù)庫(kù)Cassandra中的Commitlog,記錄哪些交易已經(jīng)從內(nèi)存中輸出到了目標(biāo)文件。日志快照文件采用循環(huán)覆蓋的方式,限定文件大小或記錄數(shù),具體根據(jù)交易系統(tǒng)情況而定。
2.5 日志恢復(fù)
對(duì)于突發(fā)斷電、系統(tǒng)崩潰的情況,內(nèi)存中未及時(shí)輸出的日志會(huì)全部丟失,此步用于恢復(fù)丟失的日志信息。
具體步驟如下:
(1)讀取持久化日志文件,逐條取出對(duì)應(yīng)的tkey和msg并進(jìn)行a類(lèi)提交;
(2)讀取日志快照文件,逐個(gè)取tkey,若tkey在Lmap中,則說(shuō)明此tkey對(duì)應(yīng)的日志已輸出,將此tkey從Lmap中移除,否則輸出日志后移除。
(3)清空持久化日志文件和日志快照文件,為下一次使用做準(zhǔn)備。
在日志恢復(fù)過(guò)程中,日志系統(tǒng)不接收交易系統(tǒng)的任何日志提交。在日志恢復(fù)完成后,日志系統(tǒng)重新回到正常的工作狀態(tài)。
3 關(guān)鍵參數(shù)
此方案實(shí)施過(guò)程中,有幾個(gè)重要的參數(shù),如超時(shí)時(shí)間、持久化日志文件大小、日志快照文件大小或記錄數(shù)等。超時(shí)時(shí)間控制著日志輸出的時(shí)機(jī),直接影響著日志系統(tǒng)的性能。而持久化日志文件大小和日志快照文件大小、記錄數(shù)決定著日志系統(tǒng)的完整性。文件大小設(shè)定過(guò)大,則日志恢復(fù)過(guò)程可能漫長(zhǎng);文件過(guò)小,可能無(wú)法完全恢復(fù)丟失的日志。
4 結(jié)束語(yǔ)
本文實(shí)現(xiàn)了一種高并發(fā)環(huán)境下交易日志的連續(xù)有序輸出的方法,大大提高日志的可讀性、友好性,一方面改善了人工排查問(wèn)題時(shí)的日志環(huán)境,減少排查時(shí)間。另一方面,簡(jiǎn)化甚至消除了日志二次處理的工作。
參考文獻(xiàn)
[1]嚴(yán)蔚敏,吳偉民編著.數(shù)據(jù)結(jié)構(gòu)(C語(yǔ)言版)[M].北京:清華大學(xué)出版社,2010.
[2]Log4j. http://logging.apache.org/log4j/1.2/manual.html,2002.
[3]郭鵬著.Cassandra實(shí)戰(zhàn)[M].北京:機(jī)械工業(yè)出版社,2011.
作者單位
中國(guó)銀聯(lián)股份有限公司 上海市 201201endprint
摘 要
本文提出了一種在高并發(fā)環(huán)境下交易日志連續(xù)輸出的機(jī)制。該方法能夠接受日志的并發(fā)無(wú)序提交,根據(jù)日志中交易的交易主鍵將日志進(jìn)行邏輯劃分,使得同一筆交易日志高度內(nèi)聚,保證了日志的連續(xù)輸出,大大提高了日志的可讀性和友好性,減少甚至避免了日志分析中對(duì)日志的額外處理。
【關(guān)鍵詞】交易日志 高并發(fā) 連續(xù)輸出
交易日志對(duì)現(xiàn)代交易系統(tǒng)具有極其重要的意義,其作用主要有三個(gè):?jiǎn)栴}排查、交易信息歸檔、交易分析與挖掘。交易日志完整記錄了每筆交易的具體執(zhí)行路徑。通過(guò)人工查看日志,可以精確把握一筆交易成功、失敗以及其他異常信息。目前,聯(lián)機(jī)交易系統(tǒng)在高并發(fā)環(huán)境下,日志的輸出通常是不連續(xù)的。一筆交易的日志中無(wú)規(guī)律地穿插著其他交易的日志信息,這樣在日志查閱、問(wèn)題排查時(shí)非常不便,需要在現(xiàn)有日志基礎(chǔ)上進(jìn)一步將一筆交易從眾多交易日志中隔離或抽取出來(lái)才能得到有效的日志信息。
1 系統(tǒng)原理
本文提出一種處理機(jī)制,在日志被輸出到目標(biāo)日志文件之前,在內(nèi)存緩沖區(qū)中對(duì)日志進(jìn)行分揀,并按照一定的策略或在一定的時(shí)機(jī)輸出日志,使得每筆交易日志高度內(nèi)聚,即使在高并發(fā)環(huán)境下亦不存在穿插的現(xiàn)象,同時(shí)保證單筆交易日志內(nèi)部有序。
工作原理如圖1所示。
按照標(biāo)號(hào),1)首先接收交易系統(tǒng)日志提交,2)將日志做持久化處理,3)然后將日志交由日志處理模塊進(jìn)行實(shí)時(shí)分揀,4)并按照一定的輸出策略進(jìn)行日志輸出,5)最后記錄日志快照。對(duì)于意外斷電或系統(tǒng)崩潰的情況,緩沖區(qū)內(nèi)的日志因沒(méi)能及時(shí)輸出而丟失。下次啟動(dòng)時(shí),分別讀取持久化日志和日志快照,經(jīng)日志恢復(fù)模塊處理后交給日志處理模塊,然后強(qiáng)制輸出此部分日志,清空持久化日志和日志快照,此后便可重新接受新日志的提交,此時(shí)系統(tǒng)恢復(fù)到正常的工作狀態(tài)。
2 實(shí)施方案
由于本方法需要在內(nèi)存緩沖區(qū)內(nèi)對(duì)每條日志進(jìn)行分揀,日志在被輸出到目標(biāo)文件之前是存放在內(nèi)存中的。而對(duì)于一個(gè)應(yīng)用來(lái)說(shuō),分配的內(nèi)存大小是有限的。為了防止因日志條目不斷增長(zhǎng)造成占用的內(nèi)存無(wú)限增加,日志系統(tǒng)設(shè)定一個(gè)參數(shù):超時(shí)時(shí)間timeout。超時(shí)時(shí)間控制一筆交易的輸出時(shí)機(jī),當(dāng)當(dāng)前時(shí)間與交易上次提交時(shí)間lasttime的間隔大于超時(shí)時(shí)間時(shí),此交易的日志被立即輸出。
對(duì)于一筆交易,其都有一個(gè)確定的交易主鍵tkey。對(duì)于一條交易日志,都有一個(gè)tkey與其關(guān)聯(lián)。若任何兩條交易日志的tkey相同,則認(rèn)為它們同屬一筆交易,應(yīng)被連續(xù)輸出。
以下對(duì)各個(gè)模塊詳細(xì)闡述。
2.1 日志提交
當(dāng)交易系統(tǒng)需要記錄日志時(shí),交易系統(tǒng)向日志系統(tǒng)同時(shí)提交tkey和與tkey相關(guān)的日志信息。具體分兩類(lèi)提交:
(1)類(lèi)提交:同時(shí)提交tkey和日志正文msg。
(2)類(lèi)提交:同時(shí)提交tkey和結(jié)束標(biāo)志finish。
若日志并非一筆交易的最后一條日志,則按交易流程將日志逐條進(jìn)行a類(lèi)提交,此步向日志系統(tǒng)提交日志正文msg。若一條日志是交易的最后一條日志,則對(duì)這條日志進(jìn)行a類(lèi)提交后,同時(shí)進(jìn)行b類(lèi)提交。此時(shí)的b類(lèi)提交不含日志正文,而是日志結(jié)束標(biāo)志finish。b類(lèi)提交出現(xiàn)在交易的出口處,通知日志系統(tǒng)一筆交易已結(jié)束。一筆交易可能因交易成功、交易失敗、系統(tǒng)異常等有多個(gè)交易出口,這些出口均需設(shè)置b類(lèi)提交。當(dāng)系統(tǒng)發(fā)生了嚴(yán)重錯(cuò)誤時(shí),b類(lèi)提交可能無(wú)法正常完成,此時(shí)由超時(shí)時(shí)間控制日志的輸出。
2.2 日志持久化
為了防止意外斷電或系統(tǒng)崩潰等原因?qū)е聝?nèi)存中的日志丟失,日志系統(tǒng)在接收到交易系統(tǒng)的日志提交后,首先將日志實(shí)時(shí)地、無(wú)序地寫(xiě)入磁盤(pán),確切的說(shuō),寫(xiě)入到持久化日志文件。日志系統(tǒng)維護(hù)一個(gè)持久化日志文件,日志以行存放,每行包含tkey和msg。持久化日志文件設(shè)定文件大小,采用循環(huán)覆蓋(rotate)的方式,具體文件大小可以根據(jù)交易系統(tǒng)情況而定。另外,對(duì)于日志實(shí)時(shí)性要求很高的情況,可以通過(guò)此文件查看在緩存中尚未及時(shí)輸出的日志。
2.3 日志處理
日志系統(tǒng)內(nèi)部維護(hù)一個(gè)自定義的數(shù)據(jù)結(jié)構(gòu)Ldata,保存tkey、lasttime和一個(gè)有序鏈表Llist。Llist的每一個(gè)節(jié)點(diǎn)存放一條日志正文。同時(shí)維護(hù)一個(gè)哈希表Lmap,Lmap以tkey為key,以L(fǎng)data為value,是交易在內(nèi)存中的清單。
日志處理模塊主要負(fù)責(zé)接收日志提交和日志輸出。當(dāng)接收到交易系統(tǒng)的提交的日志時(shí),日志處理模塊進(jìn)行判斷。若是a類(lèi)提交,則在Lmap中根據(jù)tkey查找對(duì)應(yīng)的Ldata,查找失敗則根據(jù)tkey創(chuàng)建Ldata并添加到Lmap中,表明這是一筆新的交易,此時(shí)Ldata中的lasttime為當(dāng)前時(shí)間,Llist中保存著這筆交易的第一條日志;查找成功則更新Ldata的lasttime為當(dāng)前時(shí)間,并將日志正文添加到Llist中;若是b類(lèi)提交,則按照提交順序依次輸出Llist中的日志,將tkey從Lmap中移除,并在快照文件中記錄相應(yīng)的tkey。
另外,對(duì)日志輸出進(jìn)行超時(shí)控制,必要時(shí)強(qiáng)制輸出交易日志。具體來(lái)講,遍歷Lmap,按tkey逐個(gè)取Ldata。判斷當(dāng)前時(shí)間與lasttime的差值,若差值大于timeout,則表明超時(shí)發(fā)生,立即輸出,否則取下一個(gè)Ldata。日志輸出后,將其對(duì)應(yīng)的tkey從Lmap中移除,并在快照文件中記錄。
2.4 日志快照
日志快照模塊維護(hù)一個(gè)日志快照文件,記錄已順利輸出的交易的tkey。日志快照文件類(lèi)似于NOSQL數(shù)據(jù)庫(kù)Cassandra中的Commitlog,記錄哪些交易已經(jīng)從內(nèi)存中輸出到了目標(biāo)文件。日志快照文件采用循環(huán)覆蓋的方式,限定文件大小或記錄數(shù),具體根據(jù)交易系統(tǒng)情況而定。
2.5 日志恢復(fù)
對(duì)于突發(fā)斷電、系統(tǒng)崩潰的情況,內(nèi)存中未及時(shí)輸出的日志會(huì)全部丟失,此步用于恢復(fù)丟失的日志信息。
具體步驟如下:
(1)讀取持久化日志文件,逐條取出對(duì)應(yīng)的tkey和msg并進(jìn)行a類(lèi)提交;
(2)讀取日志快照文件,逐個(gè)取tkey,若tkey在Lmap中,則說(shuō)明此tkey對(duì)應(yīng)的日志已輸出,將此tkey從Lmap中移除,否則輸出日志后移除。
(3)清空持久化日志文件和日志快照文件,為下一次使用做準(zhǔn)備。
在日志恢復(fù)過(guò)程中,日志系統(tǒng)不接收交易系統(tǒng)的任何日志提交。在日志恢復(fù)完成后,日志系統(tǒng)重新回到正常的工作狀態(tài)。
3 關(guān)鍵參數(shù)
此方案實(shí)施過(guò)程中,有幾個(gè)重要的參數(shù),如超時(shí)時(shí)間、持久化日志文件大小、日志快照文件大小或記錄數(shù)等。超時(shí)時(shí)間控制著日志輸出的時(shí)機(jī),直接影響著日志系統(tǒng)的性能。而持久化日志文件大小和日志快照文件大小、記錄數(shù)決定著日志系統(tǒng)的完整性。文件大小設(shè)定過(guò)大,則日志恢復(fù)過(guò)程可能漫長(zhǎng);文件過(guò)小,可能無(wú)法完全恢復(fù)丟失的日志。
4 結(jié)束語(yǔ)
本文實(shí)現(xiàn)了一種高并發(fā)環(huán)境下交易日志的連續(xù)有序輸出的方法,大大提高日志的可讀性、友好性,一方面改善了人工排查問(wèn)題時(shí)的日志環(huán)境,減少排查時(shí)間。另一方面,簡(jiǎn)化甚至消除了日志二次處理的工作。
參考文獻(xiàn)
[1]嚴(yán)蔚敏,吳偉民編著.數(shù)據(jù)結(jié)構(gòu)(C語(yǔ)言版)[M].北京:清華大學(xué)出版社,2010.
[2]Log4j. http://logging.apache.org/log4j/1.2/manual.html,2002.
[3]郭鵬著.Cassandra實(shí)戰(zhàn)[M].北京:機(jī)械工業(yè)出版社,2011.
作者單位
中國(guó)銀聯(lián)股份有限公司 上海市 201201endprint
摘 要
本文提出了一種在高并發(fā)環(huán)境下交易日志連續(xù)輸出的機(jī)制。該方法能夠接受日志的并發(fā)無(wú)序提交,根據(jù)日志中交易的交易主鍵將日志進(jìn)行邏輯劃分,使得同一筆交易日志高度內(nèi)聚,保證了日志的連續(xù)輸出,大大提高了日志的可讀性和友好性,減少甚至避免了日志分析中對(duì)日志的額外處理。
【關(guān)鍵詞】交易日志 高并發(fā) 連續(xù)輸出
交易日志對(duì)現(xiàn)代交易系統(tǒng)具有極其重要的意義,其作用主要有三個(gè):?jiǎn)栴}排查、交易信息歸檔、交易分析與挖掘。交易日志完整記錄了每筆交易的具體執(zhí)行路徑。通過(guò)人工查看日志,可以精確把握一筆交易成功、失敗以及其他異常信息。目前,聯(lián)機(jī)交易系統(tǒng)在高并發(fā)環(huán)境下,日志的輸出通常是不連續(xù)的。一筆交易的日志中無(wú)規(guī)律地穿插著其他交易的日志信息,這樣在日志查閱、問(wèn)題排查時(shí)非常不便,需要在現(xiàn)有日志基礎(chǔ)上進(jìn)一步將一筆交易從眾多交易日志中隔離或抽取出來(lái)才能得到有效的日志信息。
1 系統(tǒng)原理
本文提出一種處理機(jī)制,在日志被輸出到目標(biāo)日志文件之前,在內(nèi)存緩沖區(qū)中對(duì)日志進(jìn)行分揀,并按照一定的策略或在一定的時(shí)機(jī)輸出日志,使得每筆交易日志高度內(nèi)聚,即使在高并發(fā)環(huán)境下亦不存在穿插的現(xiàn)象,同時(shí)保證單筆交易日志內(nèi)部有序。
工作原理如圖1所示。
按照標(biāo)號(hào),1)首先接收交易系統(tǒng)日志提交,2)將日志做持久化處理,3)然后將日志交由日志處理模塊進(jìn)行實(shí)時(shí)分揀,4)并按照一定的輸出策略進(jìn)行日志輸出,5)最后記錄日志快照。對(duì)于意外斷電或系統(tǒng)崩潰的情況,緩沖區(qū)內(nèi)的日志因沒(méi)能及時(shí)輸出而丟失。下次啟動(dòng)時(shí),分別讀取持久化日志和日志快照,經(jīng)日志恢復(fù)模塊處理后交給日志處理模塊,然后強(qiáng)制輸出此部分日志,清空持久化日志和日志快照,此后便可重新接受新日志的提交,此時(shí)系統(tǒng)恢復(fù)到正常的工作狀態(tài)。
2 實(shí)施方案
由于本方法需要在內(nèi)存緩沖區(qū)內(nèi)對(duì)每條日志進(jìn)行分揀,日志在被輸出到目標(biāo)文件之前是存放在內(nèi)存中的。而對(duì)于一個(gè)應(yīng)用來(lái)說(shuō),分配的內(nèi)存大小是有限的。為了防止因日志條目不斷增長(zhǎng)造成占用的內(nèi)存無(wú)限增加,日志系統(tǒng)設(shè)定一個(gè)參數(shù):超時(shí)時(shí)間timeout。超時(shí)時(shí)間控制一筆交易的輸出時(shí)機(jī),當(dāng)當(dāng)前時(shí)間與交易上次提交時(shí)間lasttime的間隔大于超時(shí)時(shí)間時(shí),此交易的日志被立即輸出。
對(duì)于一筆交易,其都有一個(gè)確定的交易主鍵tkey。對(duì)于一條交易日志,都有一個(gè)tkey與其關(guān)聯(lián)。若任何兩條交易日志的tkey相同,則認(rèn)為它們同屬一筆交易,應(yīng)被連續(xù)輸出。
以下對(duì)各個(gè)模塊詳細(xì)闡述。
2.1 日志提交
當(dāng)交易系統(tǒng)需要記錄日志時(shí),交易系統(tǒng)向日志系統(tǒng)同時(shí)提交tkey和與tkey相關(guān)的日志信息。具體分兩類(lèi)提交:
(1)類(lèi)提交:同時(shí)提交tkey和日志正文msg。
(2)類(lèi)提交:同時(shí)提交tkey和結(jié)束標(biāo)志finish。
若日志并非一筆交易的最后一條日志,則按交易流程將日志逐條進(jìn)行a類(lèi)提交,此步向日志系統(tǒng)提交日志正文msg。若一條日志是交易的最后一條日志,則對(duì)這條日志進(jìn)行a類(lèi)提交后,同時(shí)進(jìn)行b類(lèi)提交。此時(shí)的b類(lèi)提交不含日志正文,而是日志結(jié)束標(biāo)志finish。b類(lèi)提交出現(xiàn)在交易的出口處,通知日志系統(tǒng)一筆交易已結(jié)束。一筆交易可能因交易成功、交易失敗、系統(tǒng)異常等有多個(gè)交易出口,這些出口均需設(shè)置b類(lèi)提交。當(dāng)系統(tǒng)發(fā)生了嚴(yán)重錯(cuò)誤時(shí),b類(lèi)提交可能無(wú)法正常完成,此時(shí)由超時(shí)時(shí)間控制日志的輸出。
2.2 日志持久化
為了防止意外斷電或系統(tǒng)崩潰等原因?qū)е聝?nèi)存中的日志丟失,日志系統(tǒng)在接收到交易系統(tǒng)的日志提交后,首先將日志實(shí)時(shí)地、無(wú)序地寫(xiě)入磁盤(pán),確切的說(shuō),寫(xiě)入到持久化日志文件。日志系統(tǒng)維護(hù)一個(gè)持久化日志文件,日志以行存放,每行包含tkey和msg。持久化日志文件設(shè)定文件大小,采用循環(huán)覆蓋(rotate)的方式,具體文件大小可以根據(jù)交易系統(tǒng)情況而定。另外,對(duì)于日志實(shí)時(shí)性要求很高的情況,可以通過(guò)此文件查看在緩存中尚未及時(shí)輸出的日志。
2.3 日志處理
日志系統(tǒng)內(nèi)部維護(hù)一個(gè)自定義的數(shù)據(jù)結(jié)構(gòu)Ldata,保存tkey、lasttime和一個(gè)有序鏈表Llist。Llist的每一個(gè)節(jié)點(diǎn)存放一條日志正文。同時(shí)維護(hù)一個(gè)哈希表Lmap,Lmap以tkey為key,以L(fǎng)data為value,是交易在內(nèi)存中的清單。
日志處理模塊主要負(fù)責(zé)接收日志提交和日志輸出。當(dāng)接收到交易系統(tǒng)的提交的日志時(shí),日志處理模塊進(jìn)行判斷。若是a類(lèi)提交,則在Lmap中根據(jù)tkey查找對(duì)應(yīng)的Ldata,查找失敗則根據(jù)tkey創(chuàng)建Ldata并添加到Lmap中,表明這是一筆新的交易,此時(shí)Ldata中的lasttime為當(dāng)前時(shí)間,Llist中保存著這筆交易的第一條日志;查找成功則更新Ldata的lasttime為當(dāng)前時(shí)間,并將日志正文添加到Llist中;若是b類(lèi)提交,則按照提交順序依次輸出Llist中的日志,將tkey從Lmap中移除,并在快照文件中記錄相應(yīng)的tkey。
另外,對(duì)日志輸出進(jìn)行超時(shí)控制,必要時(shí)強(qiáng)制輸出交易日志。具體來(lái)講,遍歷Lmap,按tkey逐個(gè)取Ldata。判斷當(dāng)前時(shí)間與lasttime的差值,若差值大于timeout,則表明超時(shí)發(fā)生,立即輸出,否則取下一個(gè)Ldata。日志輸出后,將其對(duì)應(yīng)的tkey從Lmap中移除,并在快照文件中記錄。
2.4 日志快照
日志快照模塊維護(hù)一個(gè)日志快照文件,記錄已順利輸出的交易的tkey。日志快照文件類(lèi)似于NOSQL數(shù)據(jù)庫(kù)Cassandra中的Commitlog,記錄哪些交易已經(jīng)從內(nèi)存中輸出到了目標(biāo)文件。日志快照文件采用循環(huán)覆蓋的方式,限定文件大小或記錄數(shù),具體根據(jù)交易系統(tǒng)情況而定。
2.5 日志恢復(fù)
對(duì)于突發(fā)斷電、系統(tǒng)崩潰的情況,內(nèi)存中未及時(shí)輸出的日志會(huì)全部丟失,此步用于恢復(fù)丟失的日志信息。
具體步驟如下:
(1)讀取持久化日志文件,逐條取出對(duì)應(yīng)的tkey和msg并進(jìn)行a類(lèi)提交;
(2)讀取日志快照文件,逐個(gè)取tkey,若tkey在Lmap中,則說(shuō)明此tkey對(duì)應(yīng)的日志已輸出,將此tkey從Lmap中移除,否則輸出日志后移除。
(3)清空持久化日志文件和日志快照文件,為下一次使用做準(zhǔn)備。
在日志恢復(fù)過(guò)程中,日志系統(tǒng)不接收交易系統(tǒng)的任何日志提交。在日志恢復(fù)完成后,日志系統(tǒng)重新回到正常的工作狀態(tài)。
3 關(guān)鍵參數(shù)
此方案實(shí)施過(guò)程中,有幾個(gè)重要的參數(shù),如超時(shí)時(shí)間、持久化日志文件大小、日志快照文件大小或記錄數(shù)等。超時(shí)時(shí)間控制著日志輸出的時(shí)機(jī),直接影響著日志系統(tǒng)的性能。而持久化日志文件大小和日志快照文件大小、記錄數(shù)決定著日志系統(tǒng)的完整性。文件大小設(shè)定過(guò)大,則日志恢復(fù)過(guò)程可能漫長(zhǎng);文件過(guò)小,可能無(wú)法完全恢復(fù)丟失的日志。
4 結(jié)束語(yǔ)
本文實(shí)現(xiàn)了一種高并發(fā)環(huán)境下交易日志的連續(xù)有序輸出的方法,大大提高日志的可讀性、友好性,一方面改善了人工排查問(wèn)題時(shí)的日志環(huán)境,減少排查時(shí)間。另一方面,簡(jiǎn)化甚至消除了日志二次處理的工作。
參考文獻(xiàn)
[1]嚴(yán)蔚敏,吳偉民編著.數(shù)據(jù)結(jié)構(gòu)(C語(yǔ)言版)[M].北京:清華大學(xué)出版社,2010.
[2]Log4j. http://logging.apache.org/log4j/1.2/manual.html,2002.
[3]郭鵬著.Cassandra實(shí)戰(zhàn)[M].北京:機(jī)械工業(yè)出版社,2011.
作者單位
中國(guó)銀聯(lián)股份有限公司 上海市 201201endprint