Redis 的多線程版本比 Redis 本身要快 5 倍

如果我告訴您有一個 Redis 的分支版本,它的性能比原生的 Redis 快 5 倍,而且延遲卻降低近 5 倍,你會不會想了解一下這個項目?而如果您不再需要哨兵節點並且您的副本可以接受讀取和寫入,這將有可能使分片數量減少 10 倍,這樣對你的吸引力是不是更大了呢?

我說的這個分支版本,它其實是 Redis 的一個分叉版本,名叫 KeyDB 。KeyDB 是 Redis 開源的多線程分叉版本。本文我們將提供最新的基準測試結果,並討論更強大的 KeyDB 實例如何減少集群大小以及簡化堆棧。同時我們還將討論了多線程體系結構,並演練了如何利用它實現性能的提升。

為什麼要取個新名字,為什麼要做 Redis 的分叉?

憑藉著我們不受限制的代碼庫開發能力,KeyDB 能夠在短時間內取得長足的進步,並且所走的道路將在未來幾個月內破壞整個數據庫格局。

關於為什麼首先搞一個 Redis 分叉的原因,這是因為 KeyDB 和 Redis 在如何發展方面有不同的理念。我們認為易用性、高性能和“內置動力”的方法是創造良好用戶體驗的最佳方法。儘管我們非常尊重 Redis 維護者,但我們認為 Redis 的方法過於注重代碼的簡單性,而以犧牲用戶的便利性為代價。這導致經常需要藉助外部組件和方案來解決很多常見問題。

由於存在意見分歧,因此適合 KeyDB 的功能可能不適用於 Redis。而做一個新的分叉版本可以允許我們探索這一新的開發路徑並實現可能永遠不會成為 Redis 一部分的功能。KeyDB 將與上游的 Redis 代碼變更保持同步,在適用的情況下,我們還給 Redis 提交錯誤修復和改進。我們希望這兩個項目能夠繼續發展並相互學習。

最新基準數據

KeyDB 於今年3月推出,儘管我們的性能有所提高,但我們仍然希望它能更快地發展。我們最新的基準測試數據顯示,KeyDB的單個實例的每秒操作數(圖範圍為53-5.49)比Redis(v5)的單個實例多5倍以上,而延遲(圖形範圍為4.6-5.1)近5倍:

Redis 的多線程版本比 Redis 本身要快 5 倍

Redis 的多線程版本比 Redis 本身要快 5 倍

Redis 的多線程版本比 Redis 本身要快 5 倍

Redis 的多線程版本比 Redis 本身要快 5 倍


多線程的優勢

增加 KeyDB 的單個實例/節點的功能可以減少分片的需要,並且可以大大減少數據移動的數量。您可能會問,與在單個節點上多線程化相比,在群集中運行許多Redis 節點是否可以獲得比單線程多線程更多的吞吐量?您可以像 Redis 一樣對 KeyDB 進行分片,這對數據庫進行水平擴展很有意義。但是,如果您可以選擇增加馬力而不購買第二輛車,那為什麼不呢?除分片外,還能夠擴展節點的大小,為用戶增加了新的功能和選擇。這是 Redis 與 KeyDB 之間意見分歧的其中之一。這不僅是社區中的常見討論點,還是某些圈子中的爭論點。

因此,為了回答 “用 KeyDB 運行更多線程看起來像什麼?” 這個問題,我們提供了一些基本數字,以便您對此問題有所瞭解。

以下是基準測試(操作/秒)與使用的線程數對應關係的圖表:

Redis 的多線程版本比 Redis 本身要快 5 倍

Redis 的多線程版本比 Redis 本身要快 5 倍

隨著分配更多資源給實例,您可以看到性能得到大幅提高。同時還可以可以將線程固定到某個CPU上以得到進一步的提升,但最適合您的選擇可能取決於您的設置。默認情況下,此選項是禁用的。

僅將一個線程分配給KeyDB,平均而言,與 Redis 的單個線程實例相比,它仍可保持約5%的性能提升。因此,即使添加了新功能並更改了體系結構,性能也沒有受到影響。

多線程架構

KeyDB 通過在多個線程上運行常規的 Redis 事件循環來工作。網絡 IO 和查詢解析是同時進行的。每個連接在 accept() 上分配一個線程。自旋鎖保護對核心哈希表的訪問。因為哈希表訪問非常快,所以此鎖的爭用較低。事務在EXEC命令的持續時間內保持鎖定。模塊與GIL協同工作,而GIL僅在所有服務器線程都暫停時才獲取。這保持了模塊期望的原子性保證。

與大多數數據庫不同,核心數據結構是系統中最快的部分。查詢的大部分時間來自解析REPL協議並將數據複製到網絡或從網絡複製數據。

未來的工作包括允許在連接之後重新平衡與不同線程的連接,並允許多個讀取器同時訪問哈希表

進一步優化設置

此外,KeyDB 還提供了一些有助於簡化用戶體驗的功能。例如活動副本功能已在最新的穩定版本 5 中廣泛採用並在生產中使用。此功能使您能夠在兩個主節點彼此複製,同時接受讀取和寫入操作。而且不需要哨點節點來控制故障轉移。您將獲得很高的可用性,同時最大限度地利用資源。如果尚未平衡對副本節點的讀取,則可以使用此選項將吞吐量提高一倍。這意味著從簡單的 Redis 主副本設置轉移到使用 KeyDB 的多線程活動副本設置,可以將分片需求減少多達10倍。關於主動複製的介紹可以閱讀 “Redis複製和KeyDB活動複製:優化系統資源” 這篇文字。

如何做基準測試

基準測試時最重要的是確保基準測試工具不是瓶頸。我們需要使用分配了32個內核的amazon m5.8xlarge實例,以便為我們的單實例測試產生足夠的容量。任何更低的基準測試工具將成為這些測試的瓶頸。對於測試實例,我們使用 RedisLabs 的Memtier。在我們的測試過程中,用於運行Redis和KeyDB實例的機器是amazon m5.4xlarge。

對於比較Redis和KeyDB的第一張圖表,使用了以下命令:

Memtier: memtier_benchmark -s -p 6379 –hide-histogram --authenticate --threads 32 –data-size <size>

KeyDB: keydb-server --port 6379 --requirepass --server-threads 7 --server-thread-affinity true

Redis: redis-server --port 6379 --requirepass

對於比較KeyDB ops / sec與啟用的 #threads 的圖表:

Memtier:memtier_benchmark -s -p 6379 --hide-histogram --authenticate --threads 32 --data-size 32

KeyDB已固定: keydb-server --port 6379 --requirepass --server-threads --server-thread-affinity true

KeyDB取消固定: keydb-server --port 6379 --requirepass --server-threads

文章來源:https://my.oschina.net/javayou/blog/3114474


分享到:


相關文章: