高併發賬戶記錄查詢
問題描述
高併發賬戶記錄查詢在銀行、網際網路企業、通訊企業中廣泛存在。例如:網上銀行、手機銀行、電商個人賬戶查詢、互聯網遊戲賬戶等等。這類查詢有三個共同點:
1、 資料總量非常大。使用者數量本身就非常多,再加上多年的賬戶資料,資料量可以達到幾千萬甚至上億條。
2、 訪問人數眾多。幾百萬甚至上千萬人訪問,屬於高併發查詢。
3、 不能讓使用者等待。手機、網頁要達到秒級響應,否則嚴重影響使用者體驗。
下面以某銀行賬戶活期明細查詢為例,給出這類問題的解決辦法。
某銀行共一億個活期賬戶,每個賬戶平均每月有7條資料,每年資料總量84億條。每條資料中的機構欄位,還要關聯分支機構表(幾千條)記錄。在效能上,要求單臺伺服器支援一千個以上的查詢,響應時間不能超過1秒。
有序行存
活期明細資料隨著時間增長非常快,一年就有84億條。如果放到記憶體中,需要大量記憶體空間,硬體投入成本太高,所以要放到硬碟上儲存。分支機構表只有幾千條資料,可以放在記憶體中儲存。
在硬碟上儲存,要考慮是行存還是列存。列存資料分塊壓縮,能減少遍歷資料量。但由於賬戶查詢是隨機的,整塊讀取會有額外解壓計算。而且每次取數都針對整個分塊,複雜度較高,效能不如行存。因此,這個場景要選擇行存儲存,如下圖:
圖1:行存和列存
具體的實現可以採用Java、C++、SPL等高階語言。這裡我們以程式碼量最少的SPL語言為例講解。
程式碼示例1
A1:連線生產資料庫,用遊標讀取活期存款資料,按照賬戶id排序。
A2:建立本地組表文件。
A3:建立組表,並從資料庫遊標讀取活期存款明細資料,寫入檔案。
其中,A3中的@r選項,就是建立行存檔案。一年84億條資料都匯出,時間會比較長。但是這是一次性的工作,後續就只需要追加增量資料即可。增量資料的追加方法,後面會有介紹。如果按照賬戶排序會對生產資料庫造成較大壓力,可以匯出之後基於檔案排序。排序使用SPL的sortx函式,具體用法參見函式參考。
利用索引
要利用索引提速,先要對明細檔案建立索引。由於明細資料量大,建立的索引檔案也會很大。很難全部載入到記憶體中。可以建立多級索引,如下圖:
圖2:多級快取
還是以SPL為例,建立多級索引,只需要在“程式碼示例1”的基礎上,增加一個網格即可:
程式碼示例2
A4:對行存檔案建立索引檔案。
載入的索引級別越多,佔用儲存空間越大。同時,賬戶id的跨度變小,載入到記憶體中後,索引效果也會變好。查詢時可以根據記憶體大小,儘可能載入更多級別的索引,可以有效提高查詢速度。
在查詢之前,系統初始化或者資料變動時,要預先載入多級索引,以SPL程式碼為例:
圖3:節點機自動呼叫初始化程式碼
由於我們提前準備好的活期資料是對賬戶id物理有序的,查詢時根據索引找到賬戶id後,可以在硬碟連續讀取,顯著減少磁碟IO,有效提速,如下圖:
圖4:索引和有序行存
查詢賬戶10100,先利用記憶體中預先載入的多級索引和索引檔案,快速定位到活期明細資料檔案中的位置,再連續讀取到賬戶id有變化為止。因為資料是按照賬戶id物理有序的,所以檔案的其他位置不可能再有10100賬戶的資料了。
利用索引查詢的示例程式碼如下:
程式碼示例4
A1:全程變數detailR已經快取了三級索引,現在可以基於它利用索引,按照條件取出賬戶為10100的記錄。
每個賬戶的資料量並不大,所以可以全部讀入記憶體。
活期明細前端應用(網頁或者APP),要通過集算器的JDBC驅動呼叫SPL程式碼查詢。呼叫的時候,需要將賬戶id作為引數傳給SPL程式。例如:定義一個網格引數countid,傳入賬戶id為10100。A1中的程式碼就要改為:=detailR.icursor (;ID==countid,index_detailR_id).fetch()。
關聯查詢
查到指定賬戶資料裝入記憶體後,可以將機構資料也讀入記憶體。在記憶體中關聯計算,效能可以得到保障。示例程式碼如下:
程式碼示例5
A2:讀入機構資料。
A3:賬號10100的活期明細資料關聯機構資料。
A4:將賬戶id、分支機構名稱和金額返回給前端呼叫者(網頁或者APP)。
機構資料可以在應用系統初始化的時候載入入記憶體,不必每次讀取,查詢速度更快。在上面提到的init.dfx中增加程式碼如下:
程式碼示例6
預先載入機構資料之後,查詢程式碼要在“程式碼示例5”的基礎上去掉載入機構資料的部分,修改之後的查詢程式碼如下:
程式碼示例7
A2:直接用預先載入的全程變數corp和活期明細資料關聯計算,省去了每次查詢載入機構資料的時間。
資料更新
活期明細存款是按賬號有序的,並不是按日期有序。所以,不能在末尾追加當日新增資料。活期明細幾十億條,如果每天有序歸併新資料的話,耗時太長。每月歸併一次的方案比較理想。如果將活期明細資料看成是主檔案,那麼更新原理如下圖:
圖5:資料更新
資料更新的示例程式碼如下:
程式碼示例8
A1、B1:如果是每月1日,重整檔案。
A2:從生產資料庫中讀入當日資料。
A3:將當日資料有序歸併到集算器自動生成的補檔案中。
- 2021年軟體測試的六大趨勢,必看!
- 重磅:Python/Java/C 2020年之爭!誰是你心中的NO.1?
- 新零售的未來 智慧移動機器人將發揮哪些作用?
- pytest-assume外掛(全網最詳細解釋):多重斷言執行
- UML之互動圖(序列圖與協作圖)
- 【一看】看圖說話之瓶頸
- MSSQL系列之十四 無限極分類的解決辦法
- 通過編寫“猜數字”遊戲學習 Lua
- Linux-基礎命令1
- rf IDEAS為LG電子提供WAVE ID(R)安全訪問技術
- 網工學習必備筆記——VLAN路由-三層交換
- Zabbix經驗分享-缺包常見問題處理
- 我用Pipenv來管理專案環境,大寫的爽
- Kotlin 百度離線人臉採集SDK
- CenOS 7 rpm包安裝lamp
- 取餘運算應用(2)-在glsl中
- 淺談 Ads Auction(1) - 知乎
- 感謝一直以來的陪伴,我們抽個獎吧!
- 速度數百倍之差,有人斷言KNN面臨淘汰,更快更強的ANN將取而代之 - 知乎
- 高併發賬戶記錄查詢