第三章 Redis相關知識一、Redis的優點二、為什麼Redis能這麼快?三、常用的Redis存儲結構四、從海量的KEY中查詢出某一固定字首的KEY五、如何通過Redis實作分布式鎖六、如何使用Redis實作異步隊列六、Redis如何做到持久化?七、Redis的叢集原理 | 您所在的位置:网站首页 › 肛门是指哪 › 第三章 Redis相關知識一、Redis的優點二、為什麼Redis能這麼快?三、常用的Redis存儲結構四、從海量的KEY中查詢出某一固定字首的KEY五、如何通過Redis實作分布式鎖六、如何使用Redis實作異步隊列六、Redis如何做到持久化?七、Redis的叢集原理 |
第三章 Redis相關知識 一、Redis的優點 二、為什麼Redis能這麼快? 三、常用的Redis存儲結構 1. 字元串(String) 2. 哈希(Hash) 3. 清單(List) 4. 集合(Set) 4. 有序集合(Sorted Set) 四、從海量的KEY中查詢出某一固定字首的KEY 五、如何通過Redis實作分布式鎖 1. 分布式鎖需要解決的問題 2. 分布式鎖的實作方法 3. 當大量的KEY同時過期時,應注意的問題 六、如何使用Redis實作異步隊列 1. 使用List作為隊列,RPUSH生産消息,LPOP消費消息 2. 使用BLPOP,實作異步隊列 3. 使用pub/sub,主題訂閱者模式 六、Redis如何做到持久化? 1. RDB(快照)持久化:儲存某個時間點的全量資料快照 1.1 RDB持久化的相關配置 1.2 SAVE:(使用較少)阻塞Redis的伺服器程序,知道RDB檔案被建立完畢 1.3 BGSAVE:Fork出一個子程序來建立RDB檔案,不阻塞伺服器的程序 1.4 自動化出發RDB持久化的方式 1.5 RDS持久化的缺點 2. AOF(Append-Only-File)持久化:通過儲存寫指令 2.1 AOF持久化的方式 2.2 AOF持久化的相關配置 2.3 AOF持久化的流程 3. RDB和AOF檔案共存的情況下的恢複流程 4. RDB和AOF的優缺點 5. RDB-AOF混合持久化方式(較為推薦) 七、Redis的叢集原理 1. 如何從海量的資料中快速找到所需的資料 2. 一緻性雜湊演算法 一、Redis的優點 資料類型豐富。 支援資料磁盤持久化存儲。 支援主從。 支援分片。 二、為什麼Redis能這麼快? Redis的使用能達到100000+QPS(QPS即Query Per Second,每秒内查詢次數)。 完全基于記憶體,絕大部分請求是純粹的記憶體操作,執行效率高。 資料結構簡單,對資料操作也簡單。 采用單線程,單線程也能處理高并發請求,可以通過啟動多執行個體實作多核操作,Redis使用單線程的原因是,省去了很多上下文切換線程的時間(多線程切換上下文的時間遠遠超過了讀取資料所使用的時間)。 使用多路I/O服用模型,非阻塞I/O 。 三、常用的Redis存儲結構 1. 字元串(String) 常用文法: set key value [expiration EX seconds|PX milliseconds] [NX|XX] get key 127.0.0.1:6379>SET name "zhangsan" OK 127.0.0.1:6379>GET "name" "zhangsan" 2. 哈希(Hash) Redis hash 是一個 string 類型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存儲對象。 Redis 中每個 hash 可以存儲 2^32 - 1 鍵值對(40多億)。常用文法: hmset key field value [field value ...] hgetall key舉個栗子: 127.0.0.1:6379> HMSET student name "zhangsan" age 11 sex 1 OK 127.0.0.1:6379> HGETALL student 1) "name" 2) "zhangsan" 3) "age" 4) "11" 5) "sex" 6) "1" 3. 清單(List) Redis清單是簡單的字元串清單,按照插入順序排序。你可以添加一個元素到清單的頭部(左邊)或者尾部(右邊) 一個清單最多可以包含 2^32 - 1 個元素 (4294967295, 每個清單超過40億個元素)。常用指令: lpush key value [value ...] lrange key start stop舉個栗子: 127.0.0.1:6379> LPUSH mate zhangsan (integer) 1 127.0.0.1:6379> LPUSH mate lisi (integer) 2 127.0.0.1:6379> LPUSH mate wangwu (integer) 3 127.0.0.1:6379> LRANGE mate 0 2 1) "wangwu" 2) "lisi" 3) "zhangsan" 4. 集合(Set) Redis 的 Set 是 String 類型的無序集合。集合成員是唯一的,這就意味着集合中不能出現重複的資料。 Redis 中集合是通過哈希表實作的,是以添加,删除,查找的複雜度都是 O(1)。 集合中最大的成員數為 2^32 - 1(4294967295, 每個集合可存儲40多億個成員)。常用指令: sadd key member [member ...] smembers key舉個栗子: 127.0.0.1:6379> sadd color red (integer) 1 127.0.0.1:6379> sadd color blue (integer) 1 127.0.0.1:6379> sadd color white (integer) 1 127.0.0.1:6379> sadd color yellow grew black (integer) 3 127.0.0.1:6379> smembers color 1) "blue" 2) "white" 3) "red" 4) "grew" 5) "black" 6) "yellow" 4. 有序集合(Sorted Set) Redis 有序集合和集合一樣也是 String 類型元素的集合,且不允許重複的成員 不同的是每個元素都會關聯一個 double 類型的分數。redis 正是通過分數來為集合中的成員進行從小到大的排序。 有序集合的成員是唯一的,但分數(score)卻可以重複。 集合是通過哈希表實作的,是以添加,删除,查找的複雜度都是 O(1)。 集合中最大的成員數為 2^32 - 1(4294967295, 每個集合可存儲40多億個成員)。常用指令: zadd key [NX|XX] [CH] [INCR] score member [score member ...] zrange key start stop [WITHSCORES]舉個栗子: 127.0.0.1:6379> zadd food 1 apple (integer) 1 127.0.0.1:6379> zadd food 2 apple (integer) 0 #未添加新成員,apple對應的分數改為2 127.0.0.1:6379> zadd food 1 banana (integer) 1 127.0.0.1:6379> zadd food 2 banana (integer) 0 #添未添加新成員,banana對應的分數改為2 127.0.0.1:6379> zadd food 3 banana (integer) 0 #添未添加新成員,banana對應的分數改為3 127.0.0.1:6379> zadd food 3 peach (integer) 1 127.0.0.1:6379> zadd food 2 fish (integer) 1 127.0.0.1:6379> zrange food 0 3 1) "apple" 2) "fish" 3) "banana" 4) "peach" 127.0.0.1:6379> zrange food 0 3 withscores 1) "apple" 2) "2" 3) "fish" 4) "2" 5) "banana" 6) "3" 7) "peach" 8) "3" 四、從海量的KEY中查詢出某一固定字首的KEY 需要先确定資料規模的範圍,根據資料範圍的邊界确認解決思路。 五、如何通過Redis實作分布式鎖 1. 分布式鎖需要解決的問題 互斥性:即任意時刻,隻能有一個用戶端擷取鎖,不能有多個用戶端擷取鎖; 安全性:鎖隻能由持有該用戶端所删除,不能被其他用戶端删除; 死鎖:用戶端因當機等原因無法正常釋放鎖而産生的死鎖,需要對應的設定機制避免死鎖的産生; 容錯:當部分節點當機時,用戶端仍能擷取鎖。 2. 分布式鎖的實作方法 通過使用SETNX 實作分布式鎖,(SETNX設定成功,傳回 1 。 設定失敗,傳回 0)SETNX 具有原子性,使用SETNX 對某個KEY 設值,如果設值成功,則沒有其他線程使用該KEY ;反之,設值失敗,則說明此時有其他線程或程式正在占用該KEY 。常用指令: setnx key value get key舉個栗子: 127.0.0.1:6379> exists cat (integer) 0 127.0.0.1:6379> setnx cat tom (integer) 1 127.0.0.1:6379> setnx cat tommy (integer) 0 127.0.0.1:6379> get cat "tom" 為解決SETNX 長期有效的問題,引入了EXPIRE ,來為SETNX 設定生存時間。 常用指令: expire key seconds舉個栗子: 127.0.0.1:6379> get cat "tom" 127.0.0.1:6379> expire cat 10 (integer) 1 127.0.0.1:6379> setnx cat tommy (integer) 0 127.0.0.1:6379> setnx cat tommy (integer) 1 127.0.0.1:6379> get cat "tommy" 使用EXPIRE ,但同時也存在着問題,如果在執行EXPIRE 前,SETNX 就已經完成了相應的操作,EXPIRE 就會一直占用資源,導緻無法釋放。 通過使用SETNX 實作分布式鎖(set key value [expiration EX seconds|PX milliseconds] [NX|XX] ) (1)EX second :設定鍵的過期時間second秒; (2)PX millisecond:設定鍵的過期時間喂millisecond毫秒; (3)NX:隻在鍵不存在是,才對鍵進行設定操作; (4)XX:隻在鍵已經存在時,才對鍵進行設定操作; (5)SET操作成功時,傳回OK,否則傳回nil。 舉個栗子: 127.0.0.1:6379> set rat Jerry ex 10 nx OK 127.0.0.1:6379> set rat Mickey ex 10 nx (nil) 127.0.0.1:6379> get rat "Jerry" 127.0.0.1:6379> get rat (nil) 3. 當大量的KEY同時過期時,應注意的問題 當存在集中過期的情況時,由于消除大量的KEY會耗時很長,導緻出現卡頓的情況發生 解決方案:在設定KEY的過期時間時,使用随機值,使得過期時間分散,進而解決同時消除大量KEY所産生的的卡頓現象。 六、如何使用Redis實作異步隊列 1. 使用List作為隊列,RPUSH生産消息,LPOP消費消息 缺點:LPOP不會去等待隊列中的值。而是直接消費; 改進:可以在應用層中引入SLEEP機制去重新調用LPOP重試。如果不使用SLEEP,怎麼實作異步隊列? 2. 使用BLPOP,實作異步隊列 缺點隻能供一個消費者使用常用指令: blpop key [key ...] timeout舉個栗子: 用戶端1 127.0.0.1:6379> blpop bear 30用戶端2: 127.0.0.1:6379> lpush bear panda (integer) 1用戶端2完成操作後,用戶端1的變化: 127.0.0.1:6379> blpop bear 30 1) "bear" 2) "panda" (27.55s) 3. 使用pub/sub,主題訂閱者模式 消息的釋出是無狀态的,無法保證正常到達(用戶端下線期間無法正常擷取消息)舉個栗子: 用戶端1:(建立主題topic1) 127.0.0.1:6379> SUBSCRIBE topic1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "topic1" 3) (integer) 1用戶端2: 127.0.0.1:6379> SUBSCRIBE topic1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "topic1" 3) (integer) 1用戶端3:(發送内容) 127.0.0.1:6379> PUBLISH topic1 "hello" (integer) 2此時,用戶端1 、2顯示新的内容: 1) "message" 2) "topic1" 3) "hello" 六、Redis如何做到持久化? 1. RDB(快照)持久化:儲存某個時間點的全量資料快照 1.1 RDB持久化的相關配置由于我使用的redis是安裝在windows環境,是以打開: D:\Software\Redis-x64-5.0.10 下的 redis.windows.conf 檔案 找到對應的配置: save 900 1 # 在900秒以内,産生1次寫入,就進行一次快照 save 300 10 # 在300秒以内,産生10次寫入,就進行一次快照 save 60 10000 # 在60秒以内,産生10000次寫入,就進行一次快照 save "" # 禁用rdb的配置 # 設定為yes時,表示當備份程序出錯的時候,主程序就不再進行寫入的操作了 stop-writes-on-bgsave-error yes rdbcompression yes 1.2 SAVE:(使用較少)阻塞Redis的伺服器程序,知道RDB檔案被建立完畢 127.0.0.1:6379> save # 重新生成dump.rdb檔案 OK 127.0.0.1:6379> lastsave (integer) 1618413018 1.3 BGSAVE:Fork出一個子程序來建立RDB檔案,不阻塞伺服器的程序 127.0.0.1:6379> bgsave Background saving started 127.0.0.1:6379> lastsave (integer) 1618413131 1.4 自動化出發RDB持久化的方式 根據redis.conf配置裡的SAVE m n 定時出發(使用的是BGSAVE) 主從複制時,主節點自動觸發 執行Debug Reload 指令 執行Shutdown 且沒有開啟AOF持久化時 1.5 RDS持久化的缺點 記憶體資料的全量同步,資料量大會由于I/O而嚴重影響性能 可能會因為Redis挂掉而丢失從目前至最近一次快照期間的資料 2. AOF(Append-Only-File)持久化:通過儲存寫指令 2.1 AOF持久化的方式 記錄下除了查詢意外的所有變更資料狀态的指令 以append的形式追加儲存到AOF檔案中(增量) 2.2 AOF持久化的相關配置打開: D:\Software\Redis-x64-5.0.10 下的 redis.windows.conf 檔案 找到對應的配置: appendonly no # 預設狀态為 關閉狀态 appendfilename "appendonly.aof" # 生成AOF檔案的檔案名 # appendfsync always # 緩存發生變化,就執行持久化操作 appendfsync everysec # 預設狀态,每隔一秒 # appendfsync no # 交由作業系統決定(緩存區填滿) 2.3 AOF持久化的流程 調用Fork(),建立一個子程序 子程序吧新的AOF寫入一個臨時檔案中,不依賴原來的AOF檔案 主程序持續将新的變動同步寫到記憶體和原來的AOF中 主程序擷取子程序重寫AOF完成的信号,将辛的AOF同步增量變動 使用新的AOF檔案代替舊的AOF檔案 3. RDB和AOF檔案共存的情況下的恢複流程![]() 對2^32取模,将哈希值空間組織成虛拟的圓環 |
CopyRight 2018-2019 实验室设备网 版权所有 |