成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么Redis單線程能達到百萬+QPS?

開發 后端 Redis
查看了下阿里 Redis 的性能測試報告如下,能夠達到數十萬、百萬級別的 QPS(暫時忽略阿里對 Redis 所做的優化),我們從 Redis 的設計和實現來分析一下 Redis 是怎么做的。

性能測試報告

查看了下阿里 Redis 的性能測試報告如下,能夠達到數十萬、百萬級別的 QPS(暫時忽略阿里對 Redis 所做的優化),我們從 Redis 的設計和實現來分析一下 Redis 是怎么做的。

Redis的設計與實現

其實 Redis 主要是通過三個方面來滿足這樣高效吞吐量的性能需求

  •  高效的數據結構
  •  多路復用 IO 模型
  •  事件機制

1、高效的數據結構

Redis 支持的幾種高效的數據結構 string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)

以上幾種對外暴露的數據結構它們的底層編碼方式都是做了不同的優化的,不細說了,不是本文重點。

2、多路復用 IO 模型

假設某一時刻與 Redis 服務器建立了 1 萬個長連接,對于阻塞式 IO 的做法就是,對每一條連接都建立一個線程來處理,那么就需要 1萬個線程,同時根據我們的經驗對于 IO 密集型的操作我們一般設置,線程數 = 2 * CPU 數量 + 1,對于 CPU 密集型的操作一般設置線程 = CPU 數量 + 1。

當然各種書籍或者網上也有一個詳細的計算公式可以算出更加合適準確的線程數量,但是得到的結果往往是一個比較小的值,像阻塞式 IO 這也動則創建成千上萬的線程,系統是無法承載這樣的負荷的更加彈不上高效的吞吐量和服務了。

而多路復用 IO 模型的做法是,用一個線程將這一萬個建立成功的鏈接陸續的放入 event_poll,event_poll 會為這一萬個長連接注冊回調函數,當某一個長連接準備就緒后(建立建立成功、數據讀取完成等),就會通過回調函數寫入到 event_poll 的就緒隊列 rdlist 中,這樣這個單線程就可以通過讀取 rdlist 獲取到需要的數據。為什么 Redis 是單線程,點擊這里看下這篇文章。

另外,大家可以關注微信公眾號:Java技術棧,在后臺回復:redis,可以獲取我整理的 N 篇 Redis 教程,都是干貨。

需要注意的是,除了異步 IO 外,其它的 I/O 模型其實都可以歸類為阻塞式 I/O 模型,不同的是像阻塞式 I/O 模型在第一階段讀取數據的時候,如果此時數據未準備就緒需要阻塞,在第二階段數據準備就緒后需要將數據從內核態復制到用戶態這一步也是阻塞的。而多路復用 IO 模型在第一階段是不阻塞的,只會在第二階段阻塞。

通過這種方式,就可以用 1 個或者幾個線程來處理大量的連接了,極大的提升了吐吞量

3、事件機制

Redis 客戶端與 Redis 服務端建立連接,發送命令,Redis 服務器響應命令都是需要通過事件機制來做的,如下圖   

  • 首先 redis 服務器運行,監聽套接字的 AE_READABLE 事件處于監聽的狀態下,此時連接應答處理器工作
  •  客戶端與 Redis 服務器發起建立連接,監聽套接字產生 AE_READABLE 事件,當 IO 多路復用程序監聽到其準備就緒后,將該事件壓入隊列中,由文件事件分派器獲取隊列中的事件交于連接應答處理器工作處理,應答客戶端建立連接成功,同時將客戶端 socket 的 AE_READABLE 事件壓入隊列由文件事件分派器獲取隊列中的事件交命令請求處理器關聯
  • 客戶端發送 set key value 請求,客戶端 socket 的 AE_READABLE 事件,當 IO 多路復用程序監聽到其準備就緒后,將該事件壓入隊列中,由文件事件分派器獲取隊列中的事件交于命令請求處理器關聯處理
  • 命令請求處理器關聯處理完成后,需要響應客戶端操作完成,此時將產生 socket 的 AE_WRITEABLE 事件壓入隊列,由文件事件分派器獲取隊列中的事件交于命令恢復處理器處理,返回操作結果,完成后將解除 AE_WRITEABLE 事件與命令恢復處理器的關聯

reactor模式

大體上可以說 Redis 的工作模式是,reactor 模式配合一個隊列,用一個 serverAccept 線程來處理建立請求的鏈接,并且通過 IO 多路復用模型,讓內核來監聽這些 socket,一旦某些 socket 的讀寫事件準備就緒后就對應的事件壓入隊列中,然后 worker 工作,由文件事件分派器從中獲取事件交于對應的處理器去執行,當某個事件執行完成后文件事件分派器才會從隊列中獲取下一個事件進行處理。

可以類比在 netty 中,我們一般會設置 bossGroup 和 workerGroup 默認情況下 bossGroup 為 1,workerGroup = 2 * cpu 數量,這樣可以由多個線程來處理讀寫就緒的事件,但是其中不能有比較耗時的操作如果有的話需要將其放入線程池中,不然會降低其吐吞量。在 Redis 中我們可以看做這二者的值都是 1。

為什么說存儲的值不宜過大

比如一個 string key = a,存儲了 500MB,首先讀取事件壓入隊列中,文件事件分派器從中獲取到后,交于命令請求處理器處理,此處就涉及到從磁盤中加載 500MB。

比如是普通的 SSD 硬盤,讀取速度 200MB/S,那么需要 2.5S 的讀取時間,在內存中讀取數據比較快比如 DDR4 中 50G/秒,讀取 500MB 需要 100 毫秒左右。

線程的庫一般默認 10 毫秒就算慢查詢了,大部分的指令執行時間都是微秒級別,此時其它 socket 所有的請求都將處于等待過程中,就會導致阻塞了 100 毫秒,同時又會占用較大的帶寬導致吞吐量進一步下降。 

 

責任編輯:龐桂玉 來源: Java技術棧
相關推薦

2021-03-03 08:01:58

Redis多線程程序

2023-10-15 12:23:10

單線程Redis

2020-10-30 16:20:38

Redis單線程高并發

2023-03-21 08:02:36

Redis6.0IO多線程

2019-06-17 14:20:51

Redis數據庫Java

2025-01-17 08:23:33

2023-08-17 14:12:17

2019-05-06 11:12:18

Redis高并發單線程

2019-05-07 09:44:45

Redis高并發模型

2020-11-17 10:20:53

Redis多線程單線程

2025-06-17 00:22:00

2019-02-18 08:10:53

2022-01-04 11:11:32

Redis單線程Reactor

2009-07-10 09:05:20

SwingWorker

2020-10-16 16:00:50

Redis單線程數據庫

2021-12-28 09:50:18

Redis單線程高并發

2025-04-24 08:15:00

Redis單線程線程

2019-11-25 10:13:52

Redis單線程I

2024-09-27 11:51:33

Redis多線程單線程

2019-04-02 11:20:48

Redis高并發單線程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久性色 | 亚洲一区 中文字幕 | 国产一区二区三区 | 综合久久综合久久 | 日韩视频三区 | 成人精品国产一区二区4080 | 成人做爰9片免费看网站 | 国产精品视频综合 | a级片播放 | 国产成人福利视频 | 亚欧精品 | 99久久久无码国产精品 | 最新超碰 | 九九九视频精品 | 亚洲国产精品一区二区三区 | 亚洲视频自拍 | 国产一区二区 | 日日夜夜91 | 国产精品区二区三区日本 | 黑人巨大精品欧美一区二区免费 | 日韩欧美亚洲 | 国产一区二区精品在线 | 欧美一级小视频 | 成人二区 | 国产美女一区二区 | 国产午夜精品久久久久免费视高清 | 天堂素人约啪 | 欧美黑人国产人伦爽爽爽 | 欧美日韩专区 | 精品一区二区三区在线视频 | 欧美一区二区在线观看视频 | 国产精品无 | 中文字幕精品一区久久久久 | 日韩免费中文字幕 | 99精品国产一区二区青青牛奶 | 无码日韩精品一区二区免费 | 网站国产 | 日日夜夜免费精品 | 亚洲天堂一区 | 免费一级欧美在线观看视频 | 丝袜一区二区三区 |