Redis從單線程到多線程的轉變
Redis簡介
Redis 是一個開源(BSD許可)的,內存中的數據結構存儲系統,它可以用作數據庫、緩存和消息中間件。 它支持多種類型的數據結構,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 與範圍查詢, bitmaps, hyperloglogs 和 地理空間(geospatial) 索引半徑查詢。 Redis 內置了 複製(replication),LUA腳本(Lua scripting), LRU驅動事件(LRU eviction),事務(transactions) 和不同級別的 磁盤持久化(persistence), 並通過 Redis哨兵(Sentinel)和自動 分區(Cluster)提供高可用性(high availability)。
Redis單線程時代
- Redis在起初嚴格意義上也不算純粹的單線程
單線程指的是網絡請求模塊使用了一個線程(所以不需考慮併發安全性),即一個線程處理所有網絡請求,其他模塊仍用了多個線程。比如持久化時,Redis就會開啓一個子線程去操作。
“單線程”
的Redis爲什麼會這麼快?
Redis被廣泛應用於緩存,一切皆源於Redis基於內存計算,它的讀取速度要比尋常的RMDB(關係型數據庫)快上很多。
- Redis每秒可執行大約110000次的設置(SET)操作,每秒大約可執行81000次的讀取/獲取(GET)操作。
- Redis操作具有原子性,能保證併發情況下數據的安全性。
- Rdis採用請求上的
單線程
,避免了不必要的上下文切換和線程間的資源競爭。- Redis採用瞭如非阻塞IO模型、IO的多路複用等多種IO模型。
Redis的瓶頸
先來看Redis的特性,Redis是基於內存進行操作的NoSql數據庫。
- 首先
CPU
不會成爲Redis的瓶頸,這也是爲什麼單線程的Redis依然恐怖如斯的寫照- Redis多用於高併發下做緩存,所以Redis的瓶頸最有可能是機器
內存
的大小或者網絡帶寬
6.0版本後的Redis線程問題
Redis的作者在 2019-12-19 發佈了Redis 6.0 RC1,但是即便是這種大佬也沒有逃過“真香定律”,Redis居然開始走上了多線程的潮流路線。也就是說從6.0
開始Redis就是多線程
的了,這也就意味着以後面試又多一個坑!
作者在自己博客中對新特性的介紹
原文地址:Redis 6.0 RC1 作者博客原文
Redis 6 被稱爲是 Redis 有史以來最大的一個版本,就在2020年五一期間,6.0穩定版本發佈了。下面單就線程方面先了解一下新版本特性:
redis的多線程不是你理解的多線程
- 但跟 Memcached 這種從 IO 處理到數據訪問多線程的實現模式有些差異。Redis 的多線程部分只是用來處理網絡數據的讀寫和協議解析,執行命令仍然是單線程。之所以這麼設計是不想因爲多線程而變得複雜,需要去控制 key、lua(一種輕量級腳本語言)、事務,LPUSH/LPOP(redis語法:將一個或多個值插入到列表頭部(左邊)、移出並獲取列表的第一個元素(左邊)) 等等的併發問題
- 主線程負責接收連接請求,讀事件到來(收到請求)則放到一個全局等待讀處理隊列
- 主線程處理完讀事件之後,通過 RR(Round Robin) 將這些連接分配給這些 IO 線程,然後主線程忙等待(spinlock 的效果)狀態
- IO 線程將請求數據讀取並解析完成(這裏只是讀數據和解析並不執行)
- 主線程執行所有命令並清空整個請求等待讀處理隊列(執行部分串行)
redis的多線程是默認關閉的
- Redis6.0的多線程默認是禁用的,只使用主線程。如需開啓需要修改
redis.conf
配置文件:io-threads-do-reads yes
- 線程數設置通過修改
redis.conf
配置文件:io-threads
屬性指定線程數量。關於線程數的設置,官方有一個建議:4核的機器建議設置爲2或3個線程,8核的建議設置爲6個線程,線程數一定要小於機器核數。還需要注意的是,線程數並不是越大越好,官方認爲超過了8個基本就沒什麼意義了。- 性能方面,Redis作者在RedisConf 2019的分享中提到,
開啓多線程後的Redis性能可以提升一倍左右
。