cache_timing_db是基於Redis的一個時序數據庫實現,支持高效的查詢時間分佈的數據,提供數據的加載器和查詢器,能夠實現自動化的數據加載和高性能的查詢。
背景
在我負責的一個系統中,有一個數據的同步表,每天都會同步幾萬的數據,一定時間下來,表已經累積了幾千萬的數據,這些數據實際上是十萬個站址的電量統計,平常沒用到覺得沒什麼,後面來了一個實時性較強的需求,需要通過站址號、電錶號、地址編碼以及時間來查詢一個範圍的數據,即使加了索引查詢效率依然沒有達到實時的要求,後來發現系統的Redis內存申請的還算大,就打算用Redis來緩存這部分數據。主要考慮數據在Redis如何存儲、如何高效的加載進Redis以及如何查詢等問題,因此開發了cache_timing_db。
設計思路
數據特點 :數據有個特點,就是一個站址號下有很多條數據,這些數據是按照天來分佈的,因此可以考慮一個站址的數據就放到一個Redis的數據結構裡面。
存儲實現 :使用Redis的列表來實現,用戶通過配置一個起始的日期時間以及一個單位偏移時間就能實現列表不同的下標存儲不同時間的數據,查找時只需要知道起始時間和單位偏移就可以計算出要查找的數據的下標。當然有缺點,比如日期範圍內有很多時間點沒有數據就會造成存儲的浪費,因為即使沒有數據也需要Redis開闢一個空節點,空節點也會佔用一定的內存,因此這種數據結構設計不能存儲過長時間的數據。如下圖:這就是一個站址號對應的每天同步的數據,我把這樣的一個列表稱之為一個“桶”。
序列化方式 :採用的是Protostuff作為序列化方式,相比JSON和JDK能夠更加節省內存。
加載模塊實現 :由於採用定時任務加載的方式,因此使用我的另一個框架AutoJob,支持錯誤重試,日誌記錄等。加載主要分為幾個步驟:
首先就是初始化桶,Redis的lset命令必須要求下標在列表的長度範圍內,所以必須先給桶初始化n個節點,都不放數據,初始化桶需要保證桶原來就不存在,因為通過管道的方式初始化,所以如果桶本來存在會讓桶的長度變成幾倍設置初始化長度。為了保證高效性,這裡使用的是布隆過濾器來進行過濾,如果布隆過濾器說桶存在則可能存在,如果說不存在則一定不存在,這也會導致一個問題:在使用管道存數據時可能有的桶沒有被創建,此時會出現異常,因此此時才去掃描Redis,查找不存在的桶然後創建,並且重新load這一批數據,這樣布隆過濾器可以過濾出大部分(預估配置合理的情況下)key。
其次就是保存數據,保存數據主要就是利用配置的起始時間和單位偏移來計算下標,然後放入列表。
#cache_timing_db首頁文檔和下載 #基於Redis #的簡單時序數據庫實現 #科技資訊