Redis 的第 n 次涉及,我該普及普及了

程式碼的壞味道發表於2019-07-18

redis你是怎麼發音的 ?瑞得兒思瑞迪思
曾經被一個人糾正了N多次,還是習慣瑞得兒思。可能兒化音比較洋氣

定義:單執行緒架構和非阻塞I/O多路複用模型,實現高效能的記憶體資料庫服務

官方解釋:Redis是基於記憶體的儲存。本身效能足夠高了,沒必要多執行緒。
非阻塞:不必等完全處理完一個任務就可以去處理另一個任務
多路複用:多路-指的是多個socket連線,複用-指的是複用一個執行緒。

這裡是不是有點疑惑了,單執行緒又是非阻塞多路複用。redis,到底是怎麼一回事呢?

Redis 是跑在單執行緒中的,所有的操作都是按照順序線性執行的,但是由於讀寫操作等待使用者輸入或輸出都是阻塞的,所以 I/O 操作在一般情況下往往不能直接返回,這會導致某一檔案的 I/O 阻塞導致整個程式無法對其它客戶提供服務,而 I/O 多路複用就是為了解決這個問題而出現的.

Redis 對 IO 多路複用的封裝
以 epoll 為例,瞭解 Redis 內部是如何封裝 IO 多路複用的
為了將所有 IO 複用統一,Redis 為所有 IO 複用統一了型別名 aeApiState,對於 epoll 而言,型別成員就是呼叫 epoll_wait所需要的引數
接下來就是一些對epoll介面的封裝了,包括建立 epoll(epoll_create),註冊事件(epoll_ctl),刪除事件(epoll_ctl),阻塞監聽(epoll_wait)等
建立 epoll 就是簡單的為 aeApiState 申請記憶體空間,然後將返回的指標儲存在事件驅動迴圈中\
註冊事件和刪除事件就是對 epoll_ctl 的封裝,根據操作不同選擇不同的引數\
阻塞監聽是對 epoll_wait 的封裝,在返回後將啟用的事件儲存在事件驅動中

事件驅動迴圈流程
IO 複用的封裝實現完成,那麼 Redis 是何時呼叫 IO 複用函式的呢,這就需要從 server.c/main 函式入手,可以猜測到當 main 函式初始化工作完成後,就需要進行事件驅動迴圈,而在迴圈中,會呼叫 IO 複用函式進行監聽\
在初始化完成後,main 函式呼叫了 aeMain 函式,傳入的引數就是伺服器的事件驅動

Redis 對於時間事件是採用連結串列的形式記錄的,這導致每次尋找最早超時的那個事件都需要遍歷整個連結串列,容易造成效能瓶頸。而 libevent 是採用最小堆記錄時間事件,尋找最早超時事件只需要 O(1) 的複雜度

總結一下:單執行緒指的是執行任務單執行緒先把他看做`任務盒子`,非阻塞的多路複用指的是多個使用者連線,redis自己封裝了一個`使用者盒子`把使用者連線資料放裡面,然後把使用者盒子到任務盒子去執行

基本資料型別:
扯了那麼多,會用才是王道,畢竟redis不是我能開發的。
1.redis的幾種資料型別

  • string
  • hash
  • list
  • set
  • zset

string

int:8個位元組的長整型
embstr:小於等於39個位元組的字串
raw:大於39個位元組的字串

Redis會根據當前值的型別和長度決定使用哪種內部編碼實現

string常用命令描述

序號 命令 描述
1 set key value 設定指定key的值 例:set cfun that is a goog boy
2 get key 設定指定key的值 例:get cfun 輸出:that is a goog boy
3 getrange key start end 返回 key 中字串值的子字元。例: getrange cfun 0 3 輸出:that
4 getset key value 將給定 key 的值設為 value ,並返回 key 的舊值(old value),key無舊值則返回nil ,key存在但不是字串是返回錯誤
5 getbit key offset 對 key 所儲存的字串值,獲取指定偏移量上的位(bit)
6 mget key1 [key2..] 獲取所有(一個或多個)給定 key 的值。
7 setex key seconds value 將值 value 關聯到 key ,並將 key 的過期時間設為 seconds (以秒為單位)。
8 setnx key value 只有在 key 不存在時設定 key 的值

hash

一個string型別的用來儲存key,field,value的鍵值對對映表,新增和刪除的時間複雜度都是O(1)

1.ziplist(壓縮列表):當雜湊型別元素個數小於hash-max-ziplist-entries配置(預設512個)、同時所有值都小於hash-max-ziplist-value配置(預設64位元組)時,Redis會使用ziplist作為雜湊的內部實現
2.hashtable(雜湊表):當雜湊型別無法滿足ziplist的條件時,Redis會使用hashtable作為雜湊的內部實現,因為此時ziplist的讀寫效率會下降,而hashtable的讀寫時間複雜度為O(1)

list

列表型別,儲存類似一維陣列資料

    1. ziplist(壓縮列表) 元素個數小於配置(預設512),每個元素大小小於64位元組(預設)
    2. linkedlist(連結串列) 當列表型別無法滿足ziplist的條件時,Redis會使用linkedlist作為列表的內部實現

set

集合型別

1.intset(整數集合):當集合中的元素都是整數且元素個數小於set-maxintset-entries配置(預設512個)時,Redis會選用intset來作為集合的內部實現,從而減少記憶體的使用。
2.hashtable(雜湊表):當集合型別無法滿足intset的條件時,Redis會使用hashtable作為集合的內部實現。

zset

有序結合型別

1.ziplist(壓縮列表):當有序集合的元素個數小於zset-max-ziplistentries配置(預設128個),同時每個元素的值都小於zset-max-ziplist-value配置(預設64位元組)時,Redis會用ziplist來作為有序集合的內部實現。  
2.skiplist(跳躍表):當ziplist條件不滿足時,有序集合會使用skiplist作為內部實現,因為此時ziplist的讀寫效率會下降。

cfun

相關文章