為什么單線程的 Redis 也能如此高效?多線程又帶來了什么?
提起 Redis,一個印象就是速度很快的開源內存數據庫,而且還是單線程的。
但印象有時會騙人:
- redis 6.0 后采用了多線程
- redis 7.4 之后修改了開源協議
單線程為什么速度還很快?
Redis 的客戶端調用服務器經過三個過程:發送命令、執行命令和返回結果。在命令執行階段,由于 Redis 處理命令是單線程的,在服務器上到達的所有命令不會立即被執行。所有命令都進入隊列并按順序執行。多個客戶端發送的命令執行順序不確定。但是可以確定的是兩個命令不會同時執行,避免了并發問題。這是 Redis 的基本單線程模型。
Redis 完全基于內存,數據存儲在內存中。大多數請求都是純內存操作,所以速度非常快。與傳統的磁盤文件數據存儲相比,Redis 避免了通過磁盤 I/O 讀取數據到內存的開銷。
使用單線程可以節省很多上下文切換和 CPU 消耗的時間,沒有競爭條件,不需要考慮各種鎖定問題,并且不會因為死鎖而導致性能開銷。此外,它還允許使用各種「線程不安全」的命令,例如 Lpush。
需要注意的是,當我們強調單線程時,我們指的是使用一個線程來處理網絡 I/O 和鍵值對讀寫。換句話說,一個線程處理所有網絡請求。但 Redis 的其他功能,如持久性、異步刪除和集群數據同步,實際上是由額外的線程執行。也就是說即便是在 6.0 之前的版本,也不是絕對的單線程。
Redis 雖然是純內存操作,但仍然會涉及到網絡 I/O 和磁盤 I/O(持久化操作),Redis 使用非阻塞 I/O 和 I/O 多路復用技術(如 select、poll、epoll)來處理大量的并發連接。這意味著一個線程可以同時監聽多個客戶端的連接請求,并在有數據可讀或可寫時進行處理。這種方式避免了線程在等待 I/O 操作完成時的阻塞,從而提高了系統的并發處理能力。
- 非阻塞 I/O:允許程序在 I/O 操作未完成時繼續執行其他任務。
- I/O 多路復用:通過單線程監控多個 I/O 操作,提升高并發下的效率。
官方對單線程的解釋是:因為 CPU 不是 Redis 的瓶頸,最有可能的是機器內存或網絡帶寬。由于單線程易于實現,并且 CPU 不會成為瓶頸,采用單線程解決方案是有意義的。
為什么 6.0 又采用了多線程?
Redis 在 6.0 版本引入多線程支持,主要是為了應對現代硬件架構的變化和日益復雜的業務需求,同時解決單線程模型在高并發場景下的性能瓶頸。
1.提升網絡 I/O 性能
Redis 的主要性能瓶頸在于網絡 I/O,尤其是在高并發場景下,單線程模型難以高效處理大量的網絡請求。雖然 Redis 使用了 I/O 多路復用技術(如 epoll)來優化網絡處理,但隨著硬件性能的提升,單線程的網絡 I/O 處理能力逐漸成為瓶頸。
通過引入多線程,Redis 可以將網絡 I/O 操作(如讀取客戶端請求和寫回響應)分配到多個線程并行處理,從而顯著提升網絡吞吐量和降低延遲。
2.利用多核 CPU
現在的服務器普遍配備多核 CPU,而 Redis 的單線程模型只能利用一個 CPU 核心,無法充分發揮硬件的性能潛力。通過引入多線程,Redis 可以將網絡 I/O 任務分配到多個線程,充分利用多核 CPU 的計算能力,從而提高整體性能。
3.保持核心邏輯的簡單性和一致性
Redis 6.0 的多線程模型采用了混合設計:網絡 I/O 操作由多個線程并行處理,而命令執行仍然由單線程順序執行。這種設計既保留了單線程模型的簡單性和一致性優勢(如避免線程安全問題、保證命令的原子性),又通過多線程提升了網絡 I/O 的性能。和之前的版本相比,只是將更多的事情由多線程來處理。
4.優化資源利用
在高負載場景下,單線程模型可能導致 CPU 和內存資源的浪費。通過引入多線程,Redis 可以更高效地利用系統資源,減少請求的等待時間,從而提升整體性能。
5.如何在 Redis 6.0 中啟用多線程?
默認情況下,Redis 的多線程是禁用的,如果要啟用多線程功能,需要修改 Redis 的配置文件,涉及到兩個配置項:
io-threads:
- 該選項用于設置 I/O 線程的數量。
- 默認值為 1,即不啟用多線程。
- 如果設置為大于 1 的值,Redis 會啟用多線程來處理網絡 I/O。
- 建議將 io-threads 設置為小于 CPU 核心數的值,通常為 CPU 核心數的 1/2 到 2/3。
io-threads-do-reads:
- 該選項用于控制是否啟用多線程處理讀操作。
- 默認值為 no,即不啟用多線程讀操作。
- 如果需要啟用多線程讀操作,可以將其設置為 yes。
配置示例如下:
# 啟用多線程,設置 I/O 線程數為 4
io-threads 4
# 啟用多線程處理讀操作
io-threads-do-reads yes修改了開源協議,有什么替代方案
Redis 從 7.4 版本開始修改了開源協議,從 BSD 變更為 RSALv2 和 SSPLv1 雙重許可,這意味著 Redis 在 OSI(開放源代碼促進會)定義下不再被視為嚴格的開源軟件。
這一變更對云服務商和開發者產生了較大影響,尤其是那些依賴 Redis 提供商業服務的廠商。
可以使用 Valkey 進行代替,Valkey 由 Linux 基金會支持,采用 BSD 許可證,確保了項目的開源性質。自 2024 年 3 月由 Redis 項目的貢獻者和 Linux 基金會聯合發起以來,Valkey 已經得到了包括亞馬遜云科技在內的 40 多家公司的支持和貢獻。
我現在在研究的 RAGFlow 使用的就是 Valkey 。下面是 RAGFlow 中部署 Valkey 的 docker-compose 部分代碼:
redis:
image: valkey/valkey:8
container_name: ragflow-redis
command: redis-server --requirepass ${REDIS_PASSWORD} --maxmemory 128mb --maxmemory-policy allkeys-lru
env_file: .env
ports:
- ${REDIS_PORT}:6379
volumes:
- redis_data:/data
networks:
- ragflow
restart: on-failure




























