carloszhao
當前內存數據庫發展迅速,用戶對于存儲系統的要求也越來越高,為了滿足各類業務場景的需要,騰訊云設計了新一代的內存數據庫,不但保留了原來系統的高性能、高可用等特性,同時還兼容了當前流行的Redis原生協議及使用方式。我們試圖在解決原生方案短板的基礎上,不斷創新,使得新系統同時具備易懂、易用、易維護、高可靠、低成本等特點。主要體現在以下幾個方面:
1.沿用了上一代自研系統使用共享內存的數據存儲方案,避免Redis采用AOF機制,恢復時間過久的問題,極大的降低了在升級、進程異常等場景產生的影響。同時,使用全新的快照與流水機制,解決了Fork機制造成的內存預留問題。
2.在存儲引擎方面,對于自研及開源方案進行重新分析整理,進行了再次創新,不但使用多規格Block靈活組合的存儲方式,內部數據結構同樣采用動態頁管理,對比原生引擎,極大的提高了內存使用率的同時,也降低了運行過程中產生內存碎片的機率。
3.單進程多線程的模型讓運維部署更加簡便,同時精簡模塊數量,讓請求路徑更短。
4.更加精細化的數據管理,實現快速的過期淘汰及精確的LRU特性。
5.實現了強一致特性,滿足了金融等業務對于數據一致性的強需求。
6.集群版模式中,支持了多數據庫的場景,降低用戶由主從版遷移至集群版的使用門檻。
7.存儲節點可直接轉發用戶請求,降低后臺數據變更對于客戶端的依賴,原生主從版客戶端可直接訪問集群版,無需修改代碼。
8.我們正在兼容更多的原生數據庫協議,讓更多的用戶可以無縫切換,體驗更多的新特性。
技術架構優化歷程
在架構方面我們將當前比較流行的兩層(不包含客戶端)結構簡化成了單層。
Cache則是實際的數據存儲節點。架構中不再顯式設置接入層,而是通過Cache轉發用戶請求,這樣做的好處:
·單純的存儲或接入模塊,由于對不同資源類型(CPU、網卡、內存等)需求的傾斜,無法很好的提高當前高配機型的設備利用率。也基于這個原因,理論上合并后的單層結構能更好的利用硬件資源,節約成本;
·減少模塊數量可以減少大量運維操作,便于運維人員部署及規劃資源等;
·路由更接近數據,因此在某臺Cache上進行數據遷移動作時,可以更加實時的對用戶請求做出應對(轉發至最新的目標),減少變更對用戶請求的影響。
針對一些對于接入層有強需求的場景,比如,某業務的客戶端鏈接數極多,我們也有針對性的做了優化。Cache可退化為純接入機使用,這樣可以方便的擴展為兩層結構,統一使用一套代碼,無需單獨維護。
數據分布方面,采用了全部打散的方式,即在任意一臺Cache上既有主數據也有(其他業務)備份數據,完全以Shard為粒度(物理內存單元)進行管理。
每臺Cache的內存被劃分為若干Shard,無論是主從版還是集群版,用戶的主或備數據可能落到任意Cache,分配策略支持跨機架、跨機房等。這樣做的目的有:
·不再有單純的熱備設備,減少低負載設備比例,充分利用整個集群的網卡、CPU等資源;
·當一個或若干節點異常時,利用整個集群的能力進行容錯(切換流量)與恢復(在不同節點重建備份),避免雪球效應;
·在分配時,將考慮現有設備主備Shard比例及負載,優化裝箱算法,可是集群資源更加均衡。
由于CKV+兼容Redis協議及各種使用場景,因此也區分了主從版與集群版。對于集群版來說,經過對比,數據哈希仍然采用了Pre-sharding的方式。
對于單個Shard來說,最大可管理內存為8 T,由于目前設備限制,實際最大可支持512 G,因此集群版支持的容量范圍為[1 G,512 G]×16 384 = [16 T,8 P]。當然在實際應用中,還需考慮系統內部預留資源等因素,且Shard大小及Slot對應關系的規劃也要視物理資源情況而定。
內存引擎設計,確定CKV+引擎
內存管理是內存數據庫系統中非常重要的一環,在CKV+系統的設計階段,對于引擎也是進行了大量的討論與調研,根據我們的經驗,同時吸納了多種主流內存管理體系的優點,確定了當前CKV+的引擎方案。主要特點歸納如下:
·使用共享內存,方便升級或進程異常時快速恢復;
·基于共享內存實現了紅黑樹算法,在保證性能的前提下,兼容Redis中的Hash、Set、ZSet數據類型;
·使用多規格Block作為(最小的)數據存儲單位,更加靈活同時內存空隙更小;
·使用經典的Page管理模式,優化了動態分配策略,提高了Page回收幾率,降低內存碎片率;
·用戶數據所依附的內部數據結構同樣基于Page進行動態分配,減少內部預留空間的浪費。
內存引擎的一個重要指標就是內存使用率,我們與原生Redis存儲進行了對比測試。
測試方法:使用同樣的隨機數據,分別寫入Redis及CKV+的1 G實例,對比實際存儲數據量的多少。
樣本大小:key [10,30],Value [20,100]
測試顯示,在簡單String類型的場景下,兩者存儲量近似,但在稍復雜的結構中,CKV+則可以存儲更多的用戶數據。
大膽嘗試,采用單進程多線程模型
對于內存數據庫來說,高性能仍然是大前提,而開發過程中使用的線程模型及框架對于這個層面影響較大。因此在設計初始,我們對于這部分也做了大膽嘗試。
首先,我們使用了單進程多線程的模式,而非大多開源系統的單進程單線程的路數,一方面可以更好的利用整機資源,另一方面也能降低運維門檻。對于多線程來說,需要解決的主要問題有如下幾點:
·若干線程共同管理內存則勢必需要引入鎖,而高配機型核數多、線程多,加鎖可能帶來毛刺;
·單個進程需要管理多個業務數據,特別是主從版,每塊內存Shard容量較大,難免有比較龐大的kv數據,同時主從版支持部分耗時操作,需要盡量減少實例間的相互影響;
·線程間通信或共享數據的代價要小,如同步路由信息等;
·同時要考慮諸如線程上下文切換、CPU緩存命中率、IO等因素。
在進行了一系列的調研工作后,最終確定線程模型為:每個物理核啟動一個線程,管理若干內存Shard。
使用這種模式的主要考慮:
·具體內存的操作僅由某一個CPU處理,避免加鎖,某個Shard出現熱點時,對其他線程管理的實例影響較小;
·在管理實例數量不多的情況下,空閑CPU可以處理網絡及磁盤IO,以及請求的編解碼等工作,提高整機資源利用率;
·線程間不存在依賴或競爭關系,避免不必要的損耗。
騰訊云新一代內存數據庫不但全面兼容了Redis的數據結構及使用方法,同時解決了原生方案在備份、容災等方面的不足。在性能方面,我們并沒有滿足于現狀,后續還將更細致的優化邏輯流程,并引入DPDK等特性,進一步提升系統性能。成本也是我們關注的重點,當前的系統架構與線程模型能更好的適應不斷提升的硬件設備性能,提高硬件資源的利用率,同時,我們也將引進冷熱數據分離等技術,在保證性能的前提下,更好的為用戶節省成本。