這是我參與8月更文挑戰的第4天,活動詳情查看:8月更文挑戰redis
./redis-benchmark -t set,lpush -n 100000 -q
SET: 82101.80 requests per second
LPUSH: 82440.23 requests per second
複製代碼
在本身的電腦上測試SET和LPUSH10萬次,能夠發現每秒SET和LPUSH大概在8w多,接近官方說的單機10w qps的寫。數據庫
redis徹底是基於內存的,絕大部分請求是純粹的內存操做,因此很是快速。markdown
redis目前支持5種數據類型(string、list、hash、set、zset),數據結構相對簡單,操做起來也相對快速。網絡
sds數據結構數據結構
對於string來講,redis採用SDS方式來組織數據:多線程
這種數據的核心思想就是空間換時間併發
len=13
,那麼也分配free=13
,最後buf=13+13+1=27
len=30M
,分配free=1M
,最後buf=30M+1M+1byte
len=13
,free=13
的字符串,這時候若是字符變短了len=10
,那麼額外的3個byte的空間也不會回收,先放在free裏面,這時候free=16
經過這種分配方式,某些場景下能夠減小內存申請的次數,從而達到必定的快速socket
跳躍表svn
redis的有序集合,採用的跳躍表的數據結構,經過層來加快訪問其餘節點oop
每一個節點會隨機一個層高,好比o1節點能夠經過L4層直接跳到o3,跨度是2,redis的有序集合就是經過這種方式來加快節點之間的訪問的。
redis採用單線程模型,單線程的好處在於避免了多線程對數據競爭的問題,加鎖的問題,上下文切換的問題。
據官方解釋,redis的瓶頸不在cpu,而在內存或者網絡的帶寬,綜合考慮而後就採用了單線程。這裏說的單線程是指處理網絡請求時只是用一個線程
,redis自己在持久化的時候仍是會用到額外的線程的。
redis4.0的多線程
redis4.0開始也支持了多線程,固然只是針對部分命令採用的是多線程,例如:UNLINK
、FLUSHALL
、ASYNC
、FLUSHDB
。引入這些的目的是:在某些狀況下,儘量的提高效率,假設有一個key大到幾十M,這時DEL這個key的時候,可能會短暫的阻塞,這時若是用unlink來刪除,剛開始只是刪除這個key,真正的value是後臺線程去刪除的。
redis採用了非阻塞的IO多路複用技術。redis自己就是一個事件驅動程序,redis把socket抽象成文件事件。這裏說的IO多路複用就是文件事件處理器以單線程的方式,來監聽相關的套接字(accept、read、write、close)。
因爲IO多路複用程序是一個單線程,那麼當多個socket到來時,確定要排隊,它們老是以隊列的方式順序地處理。
C10K問題
在沒有IO多路複用的時候,假設如今有10000個客戶端鏈接(fd1-10000),可是隻有1個客戶端有發數據,然而計算機並不知道哪一個fd有數據,只能遍歷10000次,每次都要陷入內核,開銷比較大,並且實際上9999次都是浪費的。
IO多路複用
IO多路複用的意思就是多個網路IO
即爲多個TCP鏈接 複用一個進程或者線程
,這種模型最大的好處就是不用爲每一個鏈接建立一個進程或者線程。比較經典的模型就是 select
、poll
、epoll
。
redis默認採用epoll,除非系統不支持。
以上4點是單線程redis快的主要緣由。