您好,登錄后才能下訂單哦!
互聯(lián)網(wǎng)金融系統(tǒng)的核心是支付結(jié)算,而支付結(jié)算的基礎(chǔ)又是賬戶系統(tǒng)。金融賬戶系統(tǒng)的特點(diǎn)是并發(fā)量大、響應(yīng)快、交易金額大,熱點(diǎn)賬戶問(wèn)題突出。一個(gè)合格的賬戶系統(tǒng)既要解決上述問(wèn)題,又必須絕對(duì)保證資金安全。作為宜信這家互聯(lián)網(wǎng)金融公司的支付結(jié)算中心,其賬戶系統(tǒng)也必須具備上述特征。
宜信支付結(jié)算賬戶體系是客戶、用戶、賬戶三層結(jié)構(gòu),證件號(hào)和證件類型唯一確定一個(gè)客戶,客戶號(hào)和機(jī)構(gòu)號(hào)確定一個(gè)用戶,一個(gè)用戶下可開(kāi)多個(gè)不同類型的賬戶。如圖:
賬戶系統(tǒng)的基礎(chǔ)是賬戶,所有的操作都圍繞著賬戶進(jìn)行,賬戶包含以下一些屬性:
賬戶下掛在最底層的會(huì)計(jì)科目下,會(huì)計(jì)科目決定了賬戶的含義及余額變動(dòng)方向。會(huì)計(jì)科目的一些屬性如下:
宜信支付結(jié)算賬戶系統(tǒng)采用科目樹(shù)的概念,每個(gè)機(jī)構(gòu)都會(huì)綁定一個(gè)科目樹(shù)??颇繕?shù)的根節(jié)點(diǎn)是一級(jí)科目,底層的科目下掛賬戶,結(jié)構(gòu)如下:
宜信支付結(jié)算賬戶系統(tǒng)采用公司自研的分布式微服務(wù)框架,對(duì)外提供http json接口,內(nèi)部各服務(wù)間采用redis實(shí)現(xiàn)的消息隊(duì)列通訊。
宜信支付結(jié)算賬戶系統(tǒng)分為接入模塊、記賬子系統(tǒng)、開(kāi)戶子系統(tǒng)、異步記賬模塊、查詢子系統(tǒng)、定時(shí)任務(wù)子系統(tǒng)、日終子系統(tǒng)、異步日志模塊,下圖是賬務(wù)系統(tǒng)功能模塊圖:
記賬處理是賬戶系統(tǒng)的核心功能,該功能對(duì)性能的要求比較高,高并發(fā)下熱點(diǎn)賬戶問(wèn)題比較突出,資金的正確性也必須保證,并且根據(jù)業(yè)務(wù)不同,記賬的分錄也是五花八門,宜信支付結(jié)算賬戶系統(tǒng)如何應(yīng)對(duì)這些問(wèn)題,這里重點(diǎn)介紹下:
熱點(diǎn)賬戶問(wèn)題是賬戶系統(tǒng)的痛點(diǎn),也困擾了我們很久,這里著重說(shuō)下。
-- 充值時(shí)的記賬分錄是:
借方:三方支付待清算賬戶(+)
貸方:個(gè)人余額賬戶(+)
當(dāng)大量用戶充值時(shí),三方支付的待清算賬戶就是熱點(diǎn)賬戶,頻繁的增加余額。
-- 提現(xiàn)時(shí)的記賬分錄是:
借方:個(gè)人余額賬戶(-)
貸方:三方支付資產(chǎn)賬戶(-)
當(dāng)大量用戶提現(xiàn)時(shí),三方支付的資產(chǎn)賬戶就是熱點(diǎn)賬戶,頻繁的減少余額。
--業(yè)務(wù)收服務(wù)費(fèi)的記賬分錄是:
借方:個(gè)人賬戶(-)
貸方:商戶服務(wù)費(fèi)賬戶(+)
當(dāng)大量向用戶收取服務(wù)費(fèi)時(shí),商戶服務(wù)費(fèi)賬戶就是熱點(diǎn)賬戶,會(huì)頻繁增加余額。
--業(yè)務(wù)服務(wù)費(fèi)付款的記賬分錄是:
借方:商戶服務(wù)費(fèi)賬戶(-)
貸方:個(gè)人賬戶(+)
當(dāng)大量用服務(wù)費(fèi)余額向用戶付款時(shí),商戶服務(wù)費(fèi)賬戶就是熱點(diǎn)賬戶,會(huì)頻繁減少余額。
記賬時(shí),所有涉及的賬戶余額都要做update更新,高并發(fā)情況下,當(dāng)出現(xiàn)上述類型的熱點(diǎn)賬戶時(shí),由于數(shù)據(jù)庫(kù)的行級(jí)鎖,對(duì)同一賬戶的更新余額操作由并行變成串行,單個(gè)請(qǐng)求的響應(yīng)時(shí)間變長(zhǎng),從而拖垮整個(gè)記賬服務(wù)。
宜信支付結(jié)算賬戶系統(tǒng)針對(duì)上述問(wèn)題做了如下處理:
我們把熱點(diǎn)賬戶按照金額變動(dòng)方向分為加頻賬戶(余額增加頻繁)、減頻賬戶(余額扣減頻繁)、雙頻賬戶(余額增加扣減均頻繁)。
準(zhǔn)實(shí)時(shí)更新余額。先將金額變動(dòng)插入臨時(shí)表中,由定時(shí)任務(wù)按照一定頻率匯總發(fā)生額,并更新賬戶余額,而后刪除臨時(shí)記錄。當(dāng)加頻賬戶減錢余額不足時(shí),主動(dòng)去匯總發(fā)生額。這里需要考慮主動(dòng)匯總發(fā)生額和定時(shí)任務(wù)處理的并發(fā)情況,我們?cè)谠摱〞r(shí)任務(wù)執(zhí)行時(shí)設(shè)置redis鎖,防止并發(fā),主動(dòng)匯總時(shí)會(huì)去判斷這個(gè)redis鎖是否存在,如存在證明定時(shí)任務(wù)正在執(zhí)行,無(wú)需主動(dòng)匯總,可能是真的余額不足。主動(dòng)匯總同樣會(huì)設(shè)置redis鎖,定時(shí)任務(wù)同樣會(huì)判斷。
將減頻賬戶拆分多個(gè)子賬戶,減頻子賬戶設(shè)置金額報(bào)警,如果某個(gè)減頻子賬戶余額不足觸發(fā)報(bào)警,會(huì)對(duì)該子賬戶做資金歸集,將其他子賬戶余額歸集到該子賬戶(每個(gè)子賬戶設(shè)置可歸集金額限制)。如在交易過(guò)程中發(fā)現(xiàn)該子賬戶余額不足,轉(zhuǎn)向使用其他子賬戶記賬。由于拆分子賬戶,余額查詢時(shí)需要匯總各個(gè)子賬戶余額返回;記錄主賬戶流水需要記賬后余額,這里需要異步計(jì)算匯總。當(dāng)減頻賬戶加錢時(shí),需要平均分配入賬到不通的子賬戶。
將雙頻賬戶拆分多個(gè)子賬戶。加錢時(shí),準(zhǔn)實(shí)時(shí)更新余額,先將子賬戶金額變動(dòng)插入臨時(shí)表中,由定時(shí)任務(wù)按一定頻率匯總發(fā)生額,將匯總的發(fā)生額更新進(jìn)對(duì)應(yīng)的子賬戶,并刪除金額變動(dòng)記錄;減錢按照之前減頻賬戶的邏輯執(zhí)行。
高并發(fā)情況下,當(dāng)多個(gè)賬戶之前互相轉(zhuǎn)賬時(shí),可能會(huì)出現(xiàn)死鎖問(wèn)題。
例如:A余額賬戶 —> B余額賬戶(線程1) 和 B余額賬戶—>A余額賬戶(線程2) 兩個(gè)轉(zhuǎn)賬請(qǐng)求并發(fā),賬戶系統(tǒng)對(duì)每個(gè)轉(zhuǎn)賬請(qǐng)求都會(huì)更新A、B余額,這兩個(gè)更新需要在一個(gè)事務(wù)里,正常流程線程1先更新A,再更新B,線程2先更新B,再更新A,線程1更新完A后會(huì)等待B的鎖,不提交事務(wù),線程2更新完B后會(huì)等待A的鎖,不提交事務(wù),這樣兩個(gè)線程互相等待鎖,造成死鎖。
宜信支付結(jié)算賬戶系統(tǒng)針對(duì)這種情況提出了解決辦法,對(duì)賬戶號(hào)進(jìn)行排序后再更新余額,這樣每個(gè)線程都是先更新A再更新B,解決了死鎖問(wèn)題。
宜信支付結(jié)算賬戶系統(tǒng)數(shù)據(jù)庫(kù)采用Mysql,緩存采用redis。
Mysql數(shù)據(jù)庫(kù)采用主從架構(gòu),一主二從,主庫(kù)向從庫(kù)同步數(shù)據(jù)。針對(duì)一些數(shù)據(jù)量大的表進(jìn)行分表,比較有代表性的是賬戶流水表,既要按賬戶維度查詢,又要按時(shí)間維度匯總,所以針對(duì)這個(gè)特點(diǎn),冗余了一張表,一張按照賬戶分表,一張按照日期分表。
賬戶系統(tǒng)各個(gè)服務(wù)部署在同一機(jī)房,其中記賬子系統(tǒng)和異步記賬模塊部署在4個(gè)不同的物理機(jī)上,其他子系統(tǒng)和模塊部署在2個(gè)不同物理機(jī)上。最前端采用nginx實(shí)現(xiàn)負(fù)載均衡。
作者:李銳 程留允
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。