redis 6.0 的「多線程」特性讓不少標題黨高潮連連,參考圖片源自於:美圖技術團隊侵刪,核心的線程(Execute Command)仍是單線程,多線程是指網絡IO(socket)讀寫的多線程化。
以下圖所示,讀寫網絡socket中的數據是能夠用多個線程,因此Redis的多線程也叫作io thread,相關參數:「io-threads」。另外一個參數是io-threads-do-reads,這裏涉及另一個細節:多線程IO主要用在請求完成後返回結果集的過程,也就是socket寫操做,至於讀socket,單線程自己採用的多路IO複用技術,也不會產生瓶頸,所以Redis給出了一個io-threads-do-reads 參數,決定讀socket的時候是否啓用多線程。其實io-threads-do-reads是否啓用,對性能的影響並不大,最後會作一個驗證。html
################################ THREADED I/O #################################
# Redis is mostly single threaded, however there are certain threaded
# operations such as UNLINK, slow I/O accesses and other things that are
# performed on side threads.
#
# Now it is also possible to handle Redis clients socket reads and writes
# in different I/O threads. Since especially writing is so slow, normally
# Redis users use pipelining in order to speed up the Redis performances per
# core, and spawn multiple instances in order to scale more. Using I/O
# threads it is possible to easily speedup two times Redis without resorting
# to pipelining nor sharding of the instance.
#
# By default threading is disabled, we suggest enabling it only in machines
# that have at least 4 or more cores, leaving at least one spare core.
# Using more than 8 threads is unlikely to help much. We also recommend using
# threaded I/O only if you actually have performance problems, with Redis
# instances being able to use a quite big percentage of CPU time, otherwise
# there is no point in using this feature.
#
# So for instance if you have a four cores boxes, try to use 2 or 3 I/O
# threads, if you have a 8 cores, try to use 6 threads. In order to
# enable I/O threads use the following configuration directive:
#
# io-threads 4
#
# Setting io-threads to 1 will just use the main thread as usual.
# When I/O threads are enabled, we only use threads for writes, that is
# to thread the write(2) syscall and transfer the client buffers to the
# socket. However it is also possible to enable threading of reads and
# protocol parsing using the following configuration directive, by setting
# it to yes:
#
# io-threads-do-reads no
#
# Usually threading reads doesn't help much.
#
# NOTE 1: This configuration directive cannot be changed at runtime via
# CONFIG SET. Aso this feature currently does not work when SSL is
# enabled.
#
# NOTE 2: If you want to test the Redis speedup using redis-benchmark, make
# sure you also run the benchmark itself in threaded mode, using the
# --threads option to match the number of Redis threads, otherwise you'll not
# be able to notice the improvements.
上文提到過io-threads-do-reads這個參數,它是決定socket讀操做是否開啓多線程,Redis的socket讀操做採用多路IO複用技術,自己不會成爲瓶頸,因此這個參數對多線程下測試影響比較小。依舊參考這裏的這個圖 侵刪,這個io-threads-do-reads在筆者理解起來,就是socket讀的線程,是否開啓影響不大。
Redis.conf中關於此參數的註釋爲:When I/O threads are enabled, we only use threads for writes, that is to thread the write(2) syscall and transfer the client buffers to the socket. However it is also possible to enable threading of reads and protocol parsing using the following configuration directive, by setting it to yes Usually threading reads doesn't help much.
如下就該參數啓用與否進行一次對比測試redis
參考以下截圖,在開啓了兩個線程的狀況下,分別開啓和禁用io-threads-do-reads,從總體上看,性能影響差異很小。固然專業的大神能夠從源碼的角度去分析。
io-threads爲2,且啓動io-threads-do-reads數據庫
io-threads爲2,且禁動io-threads-do-readscentos
redis集羣有兩種模式:sentinel和cluster,這裏暫時先不提sentinel,來思考多線程版本的Redis和Redis Cluster的選擇問題。
Redis的Cluster解決的就是擴展性和單節點單線程的阻塞隱患,若是Redis支持了多線程(目前多線程的Redis最對不建議超出8個線程),在不考慮單個節點網卡瓶頸的狀況下,其實這兩個問題都已經解決了,單節點能夠支持多線程和充分利用多核CPU,單節點能夠支持到25W QPS,還要啥自行車?
同時要考慮到Redis cluster的痛點:
1,不支持multiple/pipline操做(第三方插件也不必定穩定)。
2,cluster中每一個主節點要掛一個從節點,無論這個節點是否是獨立的物理節點仍是單機多實例中的一個節點,終究是增長了維護成本。
3,只能使用一個數據庫
4,集羣自身擴容、縮容帶來的一系列slot遷移等性能問題,以及集羣的管理問題
這些所謂的痛點也不復存在了,因此這裏就面臨一個從新選擇的問題:是使用多線程版本的Redis,仍是使用Redis cluster?這是一個須要思考的問題。服務器
關於redis-benchmark 測試時候 ./bin/redis-benchmark -d 128 -c 200 -n 1000000 -t set -q --threads 2,涉及的兩個參數-c和--threads,我的是不太理解的
-c的解釋是:指定併發鏈接數
--threads是redis-benchmark的線程數?
對此去跟老錢(素未謀面,感謝)求證了一下,說該參數是redis-benchmark客戶端的epoll,服務器端的多路IO複用原理已經看得我七葷八素了,客戶端也是帶epoll的,仍是不太理解這二者之間的關係。網絡
以下是redis-benchmark測試過程當中部分截圖多線程