1. 程式人生 > 其它 >redis快取詳解(從入門到精通)

redis快取詳解(從入門到精通)

引言

Redis 是一個開源(BSD許可)的,記憶體中的資料結構儲存系統,它可以用作資料庫、快取和訊息中介軟體。 它支援多種型別的資料結構,如 字串(strings), 雜湊(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 與範圍查詢, bitmaps, hyperloglogs 和 地理空間(geospatial) 索引半徑查詢。 Redis 內建了 複製(replication),LUA指令碼(Lua scripting), LRU驅動事件(LRU eviction),事務(transactions) 和不同級別的 磁碟持久化(persistence), 並通過 Redis哨兵(Sentinel)和自動 分割槽(Cluster)提供高可用性(high availability)。

資料結構

Redis是基於記憶體的資料儲存服務,它支援key-value查詢操作,value存在以下五種資料型別

  • 字串(strings)
  • 雜湊(hashes)
  • 表(lists)
  • 集合(sets)
  • 有序集合(sorted sets)

redis安裝

下載

地址:http://download.redis.io/releases/

解壓

##解壓
tar -xzvf redis-6.0.6.tar.gz

編譯

進入解壓的目錄,執行make命令

##使用gcc編譯,gcc版本需要大於5.0,檢視 gcc版本:gcc -v
make

##若需要指定安裝目錄,則加PREFIX選項
make install PREFIX=/usr/local/redis

##如果gcc小於5,需要先升級gcc,依次執行以下命令
yum install centos-release-scl
yum install devtoolset-7-gcc*
scl enable devtoolset-7 bash

常用命令

String

Redis 字串資料型別的相關命令用於管理 redis 字串值,常用操作命令如下:

set key value        ##設定key的值為value
mset key1 value1 key2 value2 [key value]      ##同裡設定多個
get key        ##獲取key的value值
mget key1 key2 key3 [key]        ##同裡獲取多個key的value值
del key        ##刪除key,跟value型別無關
incr key        ##對num型的key進行++1操作,decr減1
incrby key incrememt        ##對num型的key加上increment,decrby減n
append key value        ##將value的值進行字串連線操作,加在原value末尾
strlen key      ##獲取value字串長度
setnx key value        ##只有key不存在時設定key的值
exists key1 key2 key3        ##判斷某個key是否存在,跟value型別無關,返回存在key的個數

Hash

hash 是一個 string 型別的 field(欄位) 和 value(值) 的對映表,hash 特別適合用於儲存物件

hset key field1 value1 field2 value2 [field value] ##新增key,給key設定欄位以及相應的value值,可以同裡設定多個field,hmset同樣
hget key field         ##獲得key的其中一個field欄位的value值
hmget key field         ##獲得key的一個或多個field欄位的value值
hdel key field1 field2        ##刪除key的一個或多個field欄位
hexists key field        ##判斷某個key中的field欄位是否存在
hkeys key        ##獲取key的所有存在的field欄位
hvals key        ##獲取key的所有value
hlen key        ##獲取key存在的欄位field個數
hsetnx key field value        ##當只有key中的field欄位不存在的時候,將field值設為value
hincrby key field increment        ##將key中的某個num欄位filed,自增increment 

List

Redis列表是簡單的字串列表,按照插入順序排序。你可以新增一個元素到列表的頭部(左邊)或者尾部(右邊)

lpush key element1 element2 element3    ##從左邊往右邊推,依次推e1 e2 e3,(lpushx,如果list存在,才插入)
rpush key element1 element2 element3    ##從右邊往左邊推,依次推e1 e2 e3  (rpushx,如果list存在,才插入)
lpop key    ##從左邊往外彈(取),取出最左邊的元素,取了該元素就沒了
lpop key    ##從右邊往外彈(取),取出最右邊的元素,取了該元素就沒了
lrange start end    ##取出list中某幾個值,start和end可以是正反向索引,(正向索引從最左邊0開始,反向索引從最右邊-1開始),start end都是include
lindex key index    ##根據索引取出list中的元素
llen key    ##list的長度
LSET key index value    ##設定設定list某個位置的元素

##根據引數COUNT的值,移除列表中與引數 VALUE 相等的元素。
###count > 0 : 從表頭開始向表尾搜尋,移除與 VALUE 相等的元素,數量為 COUNT 。
###count < 0 : 從表尾開始向表頭搜尋,移除與 VALUE 相等的元素,數量為 COUNT 的絕對值。
###count = 0 : 移除表中所有與 VALUE 相等的值。
lrem key count value

##將source列表中最右邊的元素取出來,再放入到destination列表中最左邊
RPOPLPUSH source destination
##將值 value 插入到列表 key 當中,位於值 pivot 之前或之後。
LINSERT key BEFORE|AFTER pivot value
BLPOP key timeout    ##彈出list中最左邊的值,如果不存在,則阻塞timout秒
BRLPOP key timeout    ##彈出list中最右邊的值,如果不存在,則阻塞timout秒
BRPOPLPUSH source destination timeout    ##將source列表中最右邊的元素取出來,再放入到destination列表中最左邊,如果source沒有元素,則阻塞timeout秒。

Set

集合Set 是 String 型別的無序集合。集合成員是唯一的,這就意味著集合中不能出現重複的資料。
Redis中集合是通過雜湊表實現的,所以新增,刪除,查詢的複雜度都是 O(1)

sadd key member1 member2 member3    ##向集合中新增1個或多個成員,自動去重
srem key memeber1 memeber2    ##移除集中中一個或多個元素
scrad key    ##獲取集合的成員數
SMEMBERS key    ##獲取集中中的所有成員
SISMEMBER key member    ##判斷memeber是否是集合key中的成員
sdiff key1 key2    ##差集(返回集合1中有的,而集合2中沒有的資料)
SDIFFSTORE destination key1 [key2]    ##將差集存在destination當中
SINTER key1 [key2]    ##交集
SINTERSTORE destination key1 [key2]    ##將交集儲存在destination
SUNION key1 key2    ##並集
SUNIONSTORE destination key1 [key2]      ##將並集儲存在destination
SMOVE source destination member    ##將元素memeber從source集合移動到destination中
spop key      ##移除並返回集合中的一個隨機元素

##返回集合中一個或多個隨機元素
###如果count>0 且 count<size,則返回count個不重複的元素,如果count>size,則返回集合的全部元素(不重複)
###如果count<0,則返回count絕對值個元素,無論count絕對值是否大於size,都有可能重複。
SRANDMEMBER key [count]

Sorted Set

有序集合和集合一樣也是 string 型別元素的集合,且不允許重複的成員。
不同的是每個元素都會關聯一個 double 型別的分數。redis 正是通過分數來為集合中的成員進行從小到大的排序。
有序集合的成員是唯一的,但分數(score)卻可以重複

ZADD key score1 member1 [score2 member2]        ##向有序集合新增一個或多個成員,或者更新已存在成員的分數
zcard key        ##返回有序集合中的成員數量
zrange key start end [withscores]        ##返回指定索引區間的memeber,withscores可以把sroce也返回來,,ZREVRANGE從高到低
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT]        ##返回分數在指定範圍內的成員
scount key min max        ##返回分數在min和max區間範圍內的成員,min和max都是Including
ZINCRBY key increment member        ##對有序集合中key的member成員分數加上increment
zrank key member        ##返回member的索引(它的索引是score排過序後的索引),ZREVRANK,從高到低
zrem key member [member ...]        ##移除有序集合中一個或多個成員
zremrangebyrank key start top        ##移除有序集合中指定rank區間的成員
zremrangebyscore key min max        ##移除有序集中中指定score區間的成員,ZREVRANGEBYSCORE從高到低
zscore key member        ##返回有序集合,成員的分數值

HyperLogLog

HyperLogLog 是用來做基數統計的演算法,HyperLogLog 的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的空間總是固定 的、並且是很小的。
在 Redis 裡面,每個 HyperLogLog 鍵只需要花費 12 KB 記憶體,就可以計算接近 2^64 個不同元素的基 數。這和計算基數時,元素越多耗費記憶體就越多的集合形成鮮明對比。
但是,因為 HyperLogLog 只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以 HyperLogLog 不能像集合那樣,返回輸入的各個元素。
比如資料集 {1, 3, 5, 7, 5, 7, 8}, 那麼這個資料集的基數集為 {1, 3, 5 ,7, 8}, 基數(不重複元素)為5。 基數估計就是在誤差可接受的範圍內,快速計算基數。

PFADD key element1 element2 element3        ##新增元素
PFCOUNT key        ##計算基數
PFMERGE destination key1 key2        ##將多個 HyperLogLog 合併為一個 HyperLogLog

bitmap

bitmap就是通過最小的單位bit來進行0或者1的設定,表示某個元素對應的值或者狀態。
一個bit的值,或者是0,或者是1;也就是說一個bit能儲存的最多資訊是2。

setbit key offset value      ##將key這個bitmap上的offset位置設為value,value只能是0或1
getbit key offset       ##獲取第offset位置上的value值

##以下的區間是的位元組為b為單位,即0 0,則第1個8個二進位制位
bitcount key [start end]     ##統計bit為1的個數,可以指定區間,如果沒有指定,則獲取全部
BITPOS key bit [start end]     ##查詢bitmap中,首個值為bit(0或1)的位置(索引),可以指定區間
bitOp        ##對二進位制位進行位運算 and or 

redis事務

multi        ##標記一個事務塊開始
exec        ##執行事務塊中的所有命令
DISCARD        ##取消事務

unwatch        ##取消watch命令對所有key的監視
watch key1 key2 ...      ##監視一個或多個key,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麼事務將被打斷。類似Java中的cas操作

其它操作

auth password        ##如果有密碼,登陸後,要輸入密碼
select index        ##選擇資料庫 0- 15 
dbsize        ##當前庫中key的數量
keys parttern        ##檢視當前庫中parttern匹配成功的所有key
flushdb      ##刪除當前庫中的所有資料
flushall        ##刪除整個redis的資料
expire key seconds        ##設定過期時間,單位秒,pexpire毫秒
EXPIREAT timestamp        ##設定過期時間,在指定時間點過期,接受unix timestamp,pexpireat毫秒時間戳
ttl key        ##返回key的過期時間,pttl毫秒
PERSIST key      ##移除key的過期時間
exists key      ##檢查key是否存在
move key dbindex      ##將當前資料庫中的Key-value移至指定的db中
rename key newname      ##為key修改名字,新名字newname
type key    ##返回key所儲存值的型別
save      ##立即生成記憶體快照rdb檔案

redis配置

基本配置

bind 0.0.0.0     ##繫結IP
port 6379      ##監聽埠
pidfile /var/run/redis_6379.pid      ##pid檔案位置
logfile ""      ##log檔案位置,預設沒有,則輸出到 /dev/null
databases 16      ##資料庫個數,預設16,即0-15
daemonize no      ##是否後臺執行
supervised no      ##  no upstart systemd auto
requirepass 123456   ##設定auth認證時的密碼123456,預設沒有密碼
rename-command FLUSHDB FSAEWQFREWQFEWQ23        ##禁用flushdb
rename-command FLUSHALL FSAEWQFREWQFEWQ32s      ##禁用flushall
maxmemory 200m      ##最大可佔用記憶體,一般設為實體記憶體的80%左右,預設大小等於實體記憶體
maxclients 10000      ##最大client連線數量
maxmemory-policy noeviction        記憶體滿了後,資料淘汰策略

redis持久化

RDB持久化方式能夠在指定的時間間隔能對你的資料進行快照儲存.
AOF持久化方式記錄每次對伺服器寫的操作,當伺服器重啟的時候會重新執行這些命令來恢復原始的資料,AOF命令以redis協議追加儲存每次寫的操作到檔案末尾.Redis還能對AOF檔案進行後臺重寫,使得AOF檔案的體積不至於過大.
如果你只希望你的資料在伺服器執行的時候存在,你也可以不使用任何持久化方式.
你也可以同時開啟兩種持久化方式, 在這種情況下, 當redis重啟的時候會優先載入AOF檔案來恢復原始的資料,因為在通常情況下AOF檔案儲存的資料集要比RDB檔案儲存的資料集要完整.

RDB記憶體快照

RDB是redis預設開啟的持久化方式

工作方式

當 Redis 需要儲存 dump.rdb 檔案時, 伺服器執行以下操作:

  • Redis 呼叫forks. 同時擁有父程序和子程序。
  • 子程序將資料集寫入到一個臨時 RDB 檔案中。
  • 當子程序完成對新 RDB 檔案的寫入時,Redis 用新 RDB 檔案替換原來的 RDB 檔案,並刪除舊的 RDB 檔案。

這種工作方式使得 Redis 可以從寫時複製(copy-on-write)機制中獲益,與AOF相比,在恢復大的資料集的時候,RDB方式會更快一些.
RDB是一個非常緊湊的檔案,它儲存了某個時間點得資料集,非常適用於資料集的備份,比如你可以在每個小時報儲存一下過去24小時內的資料,同時每天儲存過去30天的資料,這樣即使出了問題你也可以根據需求恢復到不同版本的資料集.
在命令列裡,可以通過 savebgsave,命令來手動立刻觸發生成記憶體快照

RDB配置

dbfilename dump.rdb      ##記憶體快照物理檔案地址
save 60 1000        ##該設定會讓 Redis 在滿足“ 60 秒內有至少有 1000 個鍵被改動”這一條件時, 自動儲存一次資料集,可以設定多個

##配置檔案裡面,有以下預設配置
save 900 1
save 300 10
save 60 10000

AOF日誌追加

工作方式

AOF 重寫和 RDB 建立快照一樣,都巧妙地利用了寫時複製機制:

  • Redis 執行 fork() ,現在同時擁有父程序和子程序。
  • 子程序開始將新 AOF 檔案的內容寫入到臨時檔案。
  • 對於所有新執行的寫入命令,父程序一邊將它們累積到一個記憶體快取中,一邊將這些改動追加到現有 AOF 檔案的末尾,這樣樣即使在重寫的中途發生停機,現有的 AOF 檔案也還是安全的。
  • 當子程序完成重寫工作時,它給父程序傳送一個訊號,父程序在接收到訊號之後,將記憶體快取中的所有資料追加到新 AOF 檔案的末尾。
  • 搞定!現在 Redis 原子地用新檔案替換舊檔案,之後所有命令都會直接追加到新 AOF 檔案的末尾。
    AOF吸取RDB的優點,在第一次使用AOF的時候,

AOF配置

appendfilename "appendonly.aof"        ##aof檔案儲存位置
appendonly yes        ##開啟aof功能,預設no

###aof寫入磁碟的機制,關閉aof後,可以將他們都註釋,預設是appendfsync everysec,以下三種方式3選1
# appendfsync always          ##每次有新命令追加到 AOF 檔案時就執行一次 fsync :非常慢,也非常安全
# appendfsync everysec      ##每秒 fsync 一次:足夠快(和使用 RDB 持久化差不多),並且在故障時只會丟失 1 秒鐘的資料。(預設)
# appendfsync no          ##從不 fsync :將資料交給作業系統來處理。更快,也更不安全的選擇。
推薦(並且也是預設)的措施為每秒 fsync 一次, 這種 fsync 策略可以兼顧速度和安全性。

aof-use-rdb-preamble yes        ##aof結合rdb的功能,默然開啟,建議開啟

在redis的配置檔案中,大概1000多行的位置,有一個描述

redis的AOF持久功能,實際是結合了rdb的功能的,在首次進行AOF追加的時候,會將記憶體現有的資料以RDB快照的形式儲存在aof檔案的開始位置,然後如果有追加,就會在AOF檔案中將command加入到末尾。
也可以通過命令BGREWRITEAOF,將redis現在的資料,以RDB快照的形式重寫進aof檔案中,並覆蓋aof檔案中原有的資料(命令記錄就消失,只有rdb快照,檔案變小了))。
存有rdb快照的aof檔案內容如下:

redis叢集

redis主從模式

在 Redis 複製的基礎上,使用和配置主從複製非常簡單,能使得從 Redis 伺服器(下文稱 slave)能精確得複製主 Redis 伺服器(下文稱 master)的內容。每次當 slave 和 master 之間的連線斷開時, slave 會自動重連到 master 上,並且無論這期間 master 發生了什麼, slave 都將嘗試讓自身成為 master 的精確副本。
這個系統的執行依靠三個主要的機制:

  • 當一個 master 例項和一個 slave 例項連線正常時, master 會發送一連串的命令流來保持對 slave 的更新,以便於將自身資料集的改變複製給 slave , :包括客戶端的寫入、key 的過期或被逐出等等。
  • 當 master 和 slave 之間的連線斷開之後,因為網路問題、或者是主從意識到連線超時, slave 重新連線上 master 並會嘗試進行部分重同步:這意味著它會嘗試只獲取在斷開連線期間內丟失的命令流。
  • 當無法進行部分重同步時, slave 會請求進行全量重同步。這會涉及到一個更復雜的過程,例如 master 需要建立所有資料的快照,將之傳送給 slave ,之後在資料集更改時持續傳送命令流到 slave 。

配置檔案(slave從機上配置即可)

replicaof 172.17.0.5 6379         ##在從機上指定master主機的IP和埠
masterauth 123456          ##指定主機的認證密碼
replica-read-only yes        ##從機使用只讀模式

Sentinel哨兵模式

Redis 的 Sentinel 系統用於管理多個 Redis 伺服器(instance), 該系統執行以下三個任務:

  • 監控(Monitoring): Sentinel 會不斷地檢查你的主伺服器和從伺服器是否運作正常。
  • 提醒(Notification): 當被監控的某個 Redis 伺服器出現問題時, Sentinel 可以通過 API 向管理員或者其他應用程式傳送通知。
  • 自動故障遷移(Automatic failover): 當一個主伺服器不能正常工作時, Sentinel 會開始一次自動故障遷移操作, 它會將失效主伺服器的其中一個從伺服器升級為新的主伺服器, 並讓失效主伺服器的其他從伺服器改為複製新的主伺服器; 當客戶端試圖連線失效的主伺服器時, 叢集也會向客戶端返回新主伺服器的地址, 使得叢集可以使用新主伺服器代替失效伺服器。


Redis Sentinel 是一個分散式系統, 你可以在一個架構中執行多個 Sentinel 程序(progress), 這些程序使用流言協議(gossip protocols)來接收關於主伺服器是否下線的資訊, 並使用投票協議(agreement protocols)來決定是否執行自動故障遷移, 以及選擇哪個從伺服器作為新的主伺服器。
雖然 Redis Sentinel 釋出為一個單獨的可執行檔案 redis-sentinel , 但實際上它只是一個執行在特殊模式下的 Redis 伺服器, 你可以在啟動一個普通 Redis 伺服器時通過給定 –sentinel 選項來啟動 Redis Sentinel 。

配置檔案(sentinel.conf)

##Sentinel 去監視一個名為 mymaster 的主伺服器, 
##這個主伺服器的 IP 地址為 127.0.0.1 , 埠號為 6379 , 
##而將這個主伺服器判斷為失效至少需要 2 個 Sentinel 同意 (只要同意 Sentinel 的數量不達標,自動故障遷移就不會執行)
sentinel monitor mymaster 127.0.0.1 6379 2

##master伺服器的認證密碼
sentinel auth-pass mymaster 123456          

##指定Sentinel 認為伺服器已經斷線所需的毫秒數。
##不過只有一個 Sentinel 將伺服器標記為主觀下線並不一定會引起伺服器的自動故障遷移: 
##只有在足夠數量的 Sentinel 都將一個伺服器標記為主觀下線之後, 
##伺服器才會被標記為客觀下線(objectively down, 簡稱 ODOWN ), 這時自動故障遷移才會執行。
sentinel down-after-milliseconds mymaster 60000

##多個sentinel之間投票表決超時時間
sentinel failover-timeout mymaster 180000

##parallel-syncs 選項指定了在執行故障轉移時, 
##最多可以有多少個從伺服器同時對新的主伺服器進行同步, 這個數字越小, 完成故障轉移所需的時間就越長。
sentinel parallel-syncs mymaster 1

啟動方式

##第一種
redis-server /path/to/sentinel.conf --sentinel

##第二種
redis-sentinel /path/to/sentinel.conf 

叢集啟動順序

1. 啟動sentinel叢集
2. 啟動redis master主機
3. 啟動redis slave從機

下以是當主機掛掉後,在sentinel控制檯列印的日誌資訊

需要注意的是:
sentinel監聽到master主機掉線後,會通過選舉演算法,產生新的master主機,並通知其它線上的從機(除剛剛被選為master的那臺以外)連線到新的主機上面,所以在master和slave上的認證密碼應該相同,需要在master和slave所有redis機器上面配置 masterauth password,剛剛斷掉的主機如果重新啟動的話,會被sentinel叢集當作從機,並連線到選舉產生的主機上面。同裡sentinel會將現在的master監聽資訊固化(持久化)到自己的sentinel.conf配置檔案裡

Cluster模式

為什麼要實現redis cluster?

1. 主從複製不能實現高可用
2. 隨著公司發展,使用者數量增多,併發越來越多,業務需要更高的QPS,而主從複製中單機的QPS可能無法滿足業務需求
3. 資料量的考慮,現有伺服器記憶體不能滿足業務資料的需要時,單純向伺服器新增記憶體不能達到要求,此時需要考慮分散式需求,把資料分佈到不同伺服器上
4. 網路流量需求:業務的流量已經超過伺服器的網絡卡的上限值,可以考慮使用分散式來進行分流
5. 離線計算,需要中間環節緩衝等別的需求

常見的分割槽方式

全量資料,單機Redis節點無法滿足要求,按照分割槽規則把資料分到若干個子集當中

  • 節點取餘分割槽:

    節點取餘方式是非常簡單的一種分割槽方式
    節點取餘分割槽方式有一個問題:即當增加或減少節點時,原來節點中的80%的資料會進行遷移操作,對所有資料重新進行分佈
    節點取餘分割槽方式建議使用多倍擴容的方式,例如以前用3個節點儲存資料,擴容為比以前多一倍的節點即6個節點來儲存資料,這樣只需要適移50%的資料。資料遷移之後,第一次無法從快取中讀取資料,必須先從資料庫中讀取資料,然後回寫到快取中,然後才能從快取中讀取遷移之後的資料
  • 一致性雜湊分割槽:

    對每一個key進行hash運算,被雜湊後的結果在哪個token的範圍內,則按順時針去找最近的節點,這個key將會被儲存在這個節點上。

    在上面的圖中,有4個key被hash之後的值在在n1節點和n2節點之間,按照順時針規則,這4個key都會被儲存在n2節點上,
    如果在n1節點和n2節點之間新增n5節點,當下次有key被hash之後的值在n1節點和n5節點之間,這些key就會被儲存在n5節點上面了
    在上面的例子裡,新增n5節點之後,資料遷移會在n1節點和n2節點之間進行,n3節點和n4節點不受影響,資料遷移範圍被縮小很多
    同理,如果有1000個節點,此時新增一個節點,受影響的節點範圍最多隻有千分之2
    一致性雜湊一般用在節點比較多的時候
  • 虛擬槽位分配:
    虛擬槽分割槽是Redis Cluster採用的分割槽方式
    預設虛擬槽,每個槽就相當於一個數字,有一定範圍。每個槽對映一個數據子集,一般比節點數大
    1. 把16384槽按照節點數量進行平均分配,由節點進行管理
    2. 對每個key按照CRC16規則進行hash運算
    3. 把hash結果對16383進行取餘
    4. 把餘數傳送給Redis節點
    5. 節點接收到資料,驗證是否在自己管理的槽編號的範圍
      如果在自己管理的槽編號範圍內,則把資料儲存到資料槽中,然後返回執行結果
      如果在自己管理的槽編號範圍外,則會把資料傳送給正確的節點,由正確的節點來把資料儲存在對應的槽中

需要注意的是:Redis Cluster的節點之間會共享訊息,每個節點都會知道是哪個節點負責哪個範圍內的資料槽

redis cluster槽位管理

把16384個槽平均分配給節點進行管理,每個節點只能對自己負責的槽進行讀寫操作
由於每個節點之間都彼此通訊,每個節點都知道另外節點負責管理的槽範圍

客戶端訪問任意節點時,對資料key按照CRC16規則進行hash運算,然後對運算結果對16383進行取作,如果餘數在當前訪問的節點管理的槽範圍內,則直接返回對應的資料
如果不在當前節點負責管理的槽範圍內,則會告訴客戶端去哪個節點獲取資料,由客戶端去正確的節點獲取資料

1.每個節點通過通訊都會共享Redis Cluster中槽和叢集中對應節點的關係
2.客戶端向Redis Cluster的任意節點發送命令,接收命令的節點會根據CRC16規則進行hash運算與16383取餘,計算自己的槽和對應節點
3.如果儲存資料的槽被分配給當前節點,則去槽中執行命令,並把命令執行結果返回給客戶端
4.如果儲存資料的槽不在當前節點的管理範圍內,則向客戶端返回moved重定向異常
5.客戶端接收到節點返回的結果,如果是moved異常,則從moved異常中獲取目標節點的資訊
6.客戶端向目標節點發送命令,獲取命令執行結果

key過期策略

定期刪除(主動)

redis 會將每個設定了過期時間的 key 放入到一個獨立的字典中,以後會定期遍歷這個字典來刪除到期的 key。
Redis 預設會每秒進行十次過期掃描(100ms一次),過期掃描不會遍歷過期字典中所有的 key,而是採用了一種簡單的貪心策略。

  1. 從過期字典中隨機 20 個 key;
  2. 刪除這 20 個 key 中已經過期的 key;
  3. 如果過期的 key 比率超過 1/4,那就重複步驟 1;

配置檔案

hz 10          ##預設情況下,每秒執行10次過期key掃描(100ms/次)

redis預設是每隔 100ms就隨機抽取一些設定了過期時間的key,檢查其是否過期,如果過期就刪除。注意這裡是隨機抽取的。為什麼要隨機呢?你想一想假如 redis 存了幾十萬個 key ,每隔100ms就遍歷所有的設定過期時間的 key 的話,就會給 CPU 帶來很大的負載。

惰性刪除(被動)

所謂惰性策略就是在客戶端訪問這個key的時候,redis對key的過期時間進行檢查,如果過期了就立即刪除,不會給你返回任何東西。
總結:定期刪除是集中處理,惰性刪除是零散處理。

記憶體淘汰策略

為什麼需要記憶體淘汰策略

有了以上過期策略的說明後,就很容易理解為什麼需要淘汰策略了,因為不管是定期取樣刪除還是惰性刪除都不是一種完全精準的刪除,就還是會存在key沒有被刪除掉的場景,同裡redis伺服器記憶體容量有限,所以就需要記憶體淘汰策略進行補充。
通過閱讀redis的配置檔案,所提供的記憶體淘汰策略一共有8種

淘汰策略

  1. noeviction:當記憶體使用超過配置的時候會返回錯誤,不會驅逐任何鍵
  2. allkeys-lru:加入鍵的時候,如果過限,首先通過LRU演算法驅逐最久沒有使用的鍵
  3. volatile-lru:加入鍵的時候如果過限,首先從設定了過期時間的鍵集合中驅逐最久沒有使用的鍵
  4. allkeys-random:加入鍵的時候如果過限,從所有key隨機刪除
  5. volatile-random:加入鍵的時候如果過限,從過期鍵的集合中隨機驅逐
  6. volatile-ttl:從配置了過期時間的鍵中驅逐馬上就要過期的鍵
  7. volatile-lfu:從所有配置了過期時間的鍵中驅逐使用頻率最少的鍵
  8. allkeys-lfu:從所有鍵中驅逐使用頻率最少的鍵

LRU:最久沒有使用
LFU:使用頻率最少

配置檔案

maxmemory-policy noeviction        ##redis預設採用的是noeviction策略,即容量滿了後,返回錯誤。不會淘汰任何key。