自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為什么單線程的 Redis 也能如此高效?多線程又帶來了什么?

數(shù)據(jù)庫 Redis
Redis 在 6.0 版本引入多線程支持,主要是為了應(yīng)對現(xiàn)代硬件架構(gòu)的變化和日益復(fù)雜的業(yè)務(wù)需求,同時(shí)解決單線程模型在高并發(fā)場景下的性能瓶頸。

提起 Redis,一個(gè)印象就是速度很快的開源內(nèi)存數(shù)據(jù)庫,而且還是單線程的。

但印象有時(shí)會騙人:

  • redis 6.0 后采用了多線程
  • redis 7.4 之后修改了開源協(xié)議

單線程為什么速度還很快?

Redis 的客戶端調(diào)用服務(wù)器經(jīng)過三個(gè)過程:發(fā)送命令、執(zhí)行命令和返回結(jié)果。在命令執(zhí)行階段,由于 Redis 處理命令是單線程的,在服務(wù)器上到達(dá)的所有命令不會立即被執(zhí)行。所有命令都進(jìn)入隊(duì)列并按順序執(zhí)行。多個(gè)客戶端發(fā)送的命令執(zhí)行順序不確定。但是可以確定的是兩個(gè)命令不會同時(shí)執(zhí)行,避免了并發(fā)問題。這是 Redis 的基本單線程模型。

Redis 完全基于內(nèi)存,數(shù)據(jù)存儲在內(nèi)存中。大多數(shù)請求都是純內(nèi)存操作,所以速度非???。與傳統(tǒng)的磁盤文件數(shù)據(jù)存儲相比,Redis 避免了通過磁盤 I/O 讀取數(shù)據(jù)到內(nèi)存的開銷。

使用單線程可以節(jié)省很多上下文切換和 CPU 消耗的時(shí)間,沒有競爭條件,不需要考慮各種鎖定問題,并且不會因?yàn)樗梨i而導(dǎo)致性能開銷。此外,它還允許使用各種「線程不安全」的命令,例如 Lpush。

需要注意的是,當(dāng)我們強(qiáng)調(diào)單線程時(shí),我們指的是使用一個(gè)線程來處理網(wǎng)絡(luò) I/O 和鍵值對讀寫。換句話說,一個(gè)線程處理所有網(wǎng)絡(luò)請求。但 Redis 的其他功能,如持久性、異步刪除和集群數(shù)據(jù)同步,實(shí)際上是由額外的線程執(zhí)行。也就是說即便是在 6.0 之前的版本,也不是絕對的單線程。

Redis 雖然是純內(nèi)存操作,但仍然會涉及到網(wǎng)絡(luò) I/O 和磁盤 I/O(持久化操作),Redis 使用非阻塞 I/O 和 I/O 多路復(fù)用技術(shù)(如 select、poll、epoll)來處理大量的并發(fā)連接。這意味著一個(gè)線程可以同時(shí)監(jiān)聽多個(gè)客戶端的連接請求,并在有數(shù)據(jù)可讀或可寫時(shí)進(jìn)行處理。這種方式避免了線程在等待 I/O 操作完成時(shí)的阻塞,從而提高了系統(tǒng)的并發(fā)處理能力。

  • 非阻塞 I/O:允許程序在 I/O 操作未完成時(shí)繼續(xù)執(zhí)行其他任務(wù)。
  • I/O 多路復(fù)用:通過單線程監(jiān)控多個(gè) I/O 操作,提升高并發(fā)下的效率。

官方對單線程的解釋是:因?yàn)?CPU 不是 Redis 的瓶頸,最有可能的是機(jī)器內(nèi)存或網(wǎng)絡(luò)帶寬。由于單線程易于實(shí)現(xiàn),并且 CPU 不會成為瓶頸,采用單線程解決方案是有意義的。

為什么 6.0 又采用了多線程?

Redis 在 6.0 版本引入多線程支持,主要是為了應(yīng)對現(xiàn)代硬件架構(gòu)的變化和日益復(fù)雜的業(yè)務(wù)需求,同時(shí)解決單線程模型在高并發(fā)場景下的性能瓶頸。

1.提升網(wǎng)絡(luò) I/O 性能

Redis 的主要性能瓶頸在于網(wǎng)絡(luò) I/O,尤其是在高并發(fā)場景下,單線程模型難以高效處理大量的網(wǎng)絡(luò)請求。雖然 Redis 使用了 I/O 多路復(fù)用技術(shù)(如 epoll)來優(yōu)化網(wǎng)絡(luò)處理,但隨著硬件性能的提升,單線程的網(wǎng)絡(luò) I/O 處理能力逐漸成為瓶頸。

通過引入多線程,Redis 可以將網(wǎng)絡(luò) I/O 操作(如讀取客戶端請求和寫回響應(yīng))分配到多個(gè)線程并行處理,從而顯著提升網(wǎng)絡(luò)吞吐量和降低延遲。

2.利用多核 CPU

現(xiàn)在的服務(wù)器普遍配備多核 CPU,而 Redis 的單線程模型只能利用一個(gè) CPU 核心,無法充分發(fā)揮硬件的性能潛力。通過引入多線程,Redis 可以將網(wǎng)絡(luò) I/O 任務(wù)分配到多個(gè)線程,充分利用多核 CPU 的計(jì)算能力,從而提高整體性能。

3.保持核心邏輯的簡單性和一致性

Redis 6.0 的多線程模型采用了混合設(shè)計(jì):網(wǎng)絡(luò) I/O 操作由多個(gè)線程并行處理,而命令執(zhí)行仍然由單線程順序執(zhí)行。這種設(shè)計(jì)既保留了單線程模型的簡單性和一致性優(yōu)勢(如避免線程安全問題、保證命令的原子性),又通過多線程提升了網(wǎng)絡(luò) I/O 的性能。和之前的版本相比,只是將更多的事情由多線程來處理。

4.優(yōu)化資源利用

在高負(fù)載場景下,單線程模型可能導(dǎo)致 CPU 和內(nèi)存資源的浪費(fèi)。通過引入多線程,Redis 可以更高效地利用系統(tǒng)資源,減少請求的等待時(shí)間,從而提升整體性能。

5.如何在 Redis 6.0 中啟用多線程?

默認(rèn)情況下,Redis 的多線程是禁用的,如果要啟用多線程功能,需要修改 Redis 的配置文件,涉及到兩個(gè)配置項(xiàng):

io-threads:

  • 該選項(xiàng)用于設(shè)置 I/O 線程的數(shù)量。
  • 默認(rèn)值為 1,即不啟用多線程。
  • 如果設(shè)置為大于 1 的值,Redis 會啟用多線程來處理網(wǎng)絡(luò) I/O。
  • 建議將 io-threads 設(shè)置為小于 CPU 核心數(shù)的值,通常為 CPU 核心數(shù)的 1/2 到 2/3。

io-threads-do-reads:

  • 該選項(xiàng)用于控制是否啟用多線程處理讀操作。
  • 默認(rèn)值為 no,即不啟用多線程讀操作。
  • 如果需要啟用多線程讀操作,可以將其設(shè)置為 yes。

配置示例如下:

# 啟用多線程,設(shè)置 I/O 線程數(shù)為 4
io-threads 4

# 啟用多線程處理讀操作
io-threads-do-reads yes

修改了開源協(xié)議,有什么替代方案

Redis 從 7.4 版本開始修改了開源協(xié)議,從 BSD 變更為 RSALv2 和 SSPLv1 雙重許可,這意味著 Redis 在 OSI(開放源代碼促進(jìn)會)定義下不再被視為嚴(yán)格的開源軟件。

這一變更對云服務(wù)商和開發(fā)者產(chǎn)生了較大影響,尤其是那些依賴 Redis 提供商業(yè)服務(wù)的廠商。

可以使用 Valkey 進(jìn)行代替,Valkey 由 Linux 基金會支持,采用 BSD 許可證,確保了項(xiàng)目的開源性質(zhì)。自 2024 年 3 月由 Redis 項(xiàng)目的貢獻(xiàn)者和 Linux 基金會聯(lián)合發(fā)起以來,Valkey 已經(jīng)得到了包括亞馬遜云科技在內(nèi)的 40 多家公司的支持和貢獻(xiàn)。

我現(xiàn)在在研究的 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
責(zé)任編輯:姜華 來源: 不止dotNET
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號