Redis使用了單線程架構和I/O多路複用模型來實現高性能的內存數據庫服務。每次Redis的客戶端調用都經歷了發送命令、執行命令、返回結果三個過程。由於Redis是單線程來處理命令的,因此一條命令從客戶端達到服務端不會馬上被執行,全部命令都會進入一個隊列中,而後逐個被執行。因此客戶端命令的執行順序是不肯定的,可是能夠肯定不會有兩條命令被同時執行,因此兩條incr命令不管怎麼執行最終結果都是2,不會產生併發問題,這就是Redis單線程的基本模型。可是像發送命令、返回結果、命令排隊確定不像描述的這麼簡單,Redis使用了I/O多路複用技術來解決I/O的問題。算法
一般來說,單線程處理能力要比多線程差,那麼爲何Redis使用單線程模型會達到每秒萬級別的處理能力呢?能夠將其歸結爲三點:第一,純內存訪問,Redis將全部數據放在內存中,內存的響應時長大約爲100納秒,這是Redis達到每秒萬級別訪問的重要基礎。第二,非阻塞I/O,Redis使用epoll做爲I/O多路複用技術的實現,再加上Redis自身的事件處理模型將epoll中的鏈接、讀寫、關閉都轉換爲事件,不在網絡I/O上浪費過多的時間。第三,單線程避免了線程切換和競態產生的消耗。既然採用單線程就能達到如此高的性能,那麼也不失爲一種不錯的選擇,由於單線程能帶來幾個好處:第一,單線程能夠簡化數據結構和算法的實現。若是對高級編程語言熟悉的讀者應該瞭解併發數據結構實現不但困難並且開發測試比較麻煩。第二,單線程避免了線程切換和競態產生的消耗,對於服務端開發來講,鎖和線程切換一般是性能殺手。可是單線程會有一個問題:對於每一個命令的執行時間是有要求的。若是某個命令執行過長,會形成其餘命令的阻塞,對於Redis這種高性能的服務來講是致命的,因此Redis是面向快速執行場景的數據庫。數據庫
type命令返回當前鍵的數據結構類型,它們分別是:string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合),但這些只是Redis對外的數據結構。實際上每種數據結構都有本身底層的內部編碼實現,並且是多種實現,這樣Redis會在合適的場景選擇合適的內部編碼。每種數據結構都有兩種以上的內部編碼實現,例如list數據結構包含了linkedlist和ziplist兩種內部編碼(3.2版本以前)。同時有些內部編碼,例如ziplist,能夠做爲多種外部數據結構的內部實現,能夠經過object encoding命令查詢內部編碼。編程
Redis這樣設計有兩個好處:第一,能夠改進內部編碼,而對外的數據結構和命令沒有影響,這樣一旦開發出更優秀的內部編碼,無需改動外部數據結構和命令,例如Redis3.2提供了quicklist,結合了ziplist和linkedlist二者的優點,爲列表類型提供了一種更爲優秀的內部編碼實現,而對外部用戶來講基本感知不到。第二,多種內部編碼實現能夠在不一樣場景下發揮各自的優點,例如ziplist比較節省內存,可是在列表元素比較多的狀況下,性能會有所降低,這時候Redis會根據配置選項將列表類型的內部實現轉換爲linkedlist。緩存
字符串類型的內部編碼有3種:網絡
·int:8個字節的長整型。session
·embstr:小於等於39個字節的字符串。數據結構
·raw:大於39個字節的字符串。多線程
Redis會根據當前值的類型和長度決定使用哪一種內部編碼實現。架構
緩存併發
計數
共享session、分佈式鎖
限速
哈希類型的內部編碼有兩種:
·ziplist(壓縮列表):當哈希類型元素個數小於hash-max-ziplist-entries配置(默認512個)、同時全部值都小於hash-max-ziplist-value配置(默認64字節)時,Redis會使用ziplist做爲哈希的內部實現,ziplist使用更加緊湊的結構實現多個元素的連續存儲,因此在節省內存方面比hashtable更加優秀。
·hashtable(哈希表):當哈希類型沒法知足ziplist的條件時,Redis會使用hashtable做爲哈希的內部實現,由於此時ziplist的讀寫效率會降低,而hashtable的讀寫時間複雜度爲O(1)。
用戶信息
文章詳情
3.2版本以前列表類型的內部編碼有兩種:
·ziplist(壓縮列表):當列表的元素個數小於list-max-ziplist-entries配置(默認512個),同時列表中每一個元素的值都小於list-max-ziplist-value配置時(默認64字節),Redis會選用ziplist來做爲列表的內部實現來減小內存的使用。
·linkedlist(鏈表):當列表類型沒法知足ziplist的條件時,Redis會使用linkedlist做爲列表的內部實現。
3.2版本開始列表的內部編碼均改成quicklist。
消息隊列
文章列表
集合類型的內部編碼有兩種:
·intset(整數集合):當集合中的元素都是整數且元素個數小於set-max-intset-entries配置(默認512個)時,Redis會選用intset來做爲集合的內部實現,從而減小內存的使用。
·hashtable(哈希表):當集合類型沒法知足intset的條件時,Redis會使用hashtable做爲集合的內部實現。
標籤
生成隨機數、抽獎
社交需求
zpopmax/bzpopmax、zpopmin/bzpopmin(5.0)
有序集合類型的內部編碼有兩種:
·ziplist(壓縮列表):當有序集合的元素個數小於zset-max-ziplist-entries配置(默認128個),同時每一個元素的值都小於zset-max-ziplist-value配置(默認64字節)時,Redis會用ziplist來做爲有序集合的內部實現,ziplist能夠有效減小內存的使用。
·skiplist(跳躍表):當ziplist條件不知足時,有序集合會使用skiplist做爲內部實現,由於此時ziplist的讀寫效率會降低。
排行榜