當前位置:首頁 » 文件管理 » redis緩存命令

redis緩存命令

發布時間: 2022-12-11 17:40:24

㈠ redis做mysql緩存

redis緩存其實就是把經常訪問的數據放到redis裡面,用戶查詢的時候先去redis查詢,沒有查到就執行sql語句查詢,同時把數據同步到redis裡面。redis只做讀操作,在內存中查詢速度快。

使用redis做緩存必須解決兩個問題,首先就是確定用何種數據結構存儲來自mysql的數據;確定數據結構之後就是需要確定用什麼標識來作為數據的key。
mysql是按照表存儲數據的,這些表是由若干行組成。每一次執行select查詢,mysql都會返回一個結果集,這個結果是由若干行組成的。redis有五種數據結構:列表list,哈希hash,字元串string,集合set,sorted set(有序集合),對比幾種數據結構,string和hash是比較適合存儲行的數據結構,可以把數據轉成json字元串存入redis。

全量遍歷鍵: keys pattern keys *
有人說 KEYS 相當於關系性數據的庫的 select * ,在生產環境幾乎是要禁用的

不管上面說的對不對, keys 肯定是有風險的。那我們就換一種方案,在存數據的時候。把數據的鍵存一下,也存到redis裡面選hash類型,那麼取的時候就可以直接通過這個hash獲取所有的值,自我感覺非常好用!

㈡ 如何查詢redis的緩存文件路徑

1、首先找到redis的安裝目錄,如下圖測試環境目錄,進入到/opt/install/redis-2.8.19/src,如下圖所示。

㈢ 測試技術-中間件-刪除redis緩存key值

跳板機Xshell命令操作:

執行連接> redis-cli -h {ip} -p {port} -a {password}

執行登錄> auth {password}

執行檢查> exists {key}

執行刪除> del {key}

set    #set類型

hash    #hash類型

(integer) -2    #不存在的 key

(integer) -1    #存在key ,但沒有設置剩餘生存時間

(integer) 6179 #存在key,有設置剩餘生存時間(毫秒)

> HKEYS auth.client.details

1) "\xac\xed\x00\x05t\x00\x13mih7201092011201546"   #欄位名

2) "\xac\xed\x00\x05t\x00\x13mih5288722010211719"   #欄位名

3) "\xac\xed\x00\x05t\x00\x13mih9979092010211719"   #欄位名

> HMGET auth.client.details "\xac\xed\x00\x05t\x00\x13mih2749661808171742"

https://www.runoob.com/redis/redis-strings.html

㈣ 緩存-redis 三種模式搭建和運行原理

標簽: redis 緩存 主從 哨兵 集群

本文簡單的介紹redis三種模式在linux的安裝部署和數據存儲的總結,希望可以相互交流相互提升。

對於Centos7在安裝redis之前需要進行一些常用工具的安裝:

關閉防火牆

正式安裝redis

在redis進行maketest時候會出現一系列的異常,有如下解決方案:

用redis-server啟動一下redis,做一些實驗沒什麼意義。

要把redis作為一個系統的daemon進程去運行的,每次系統啟動,redis進程一起啟動,操作不走如下:

RDB和AOF是redis的一種數據持久化的機制。 持久化 是為了避免系統在發生災難性的系統故障時導致的系統數據丟失。我們一般會將數據存放在本地磁碟,還會定期的將數據上傳雲伺服器
RDB 是redis的snapshotting,通過redis.conf中的save配置進行設置,如 save 60 1000:

AOF 是以appendonly方式進行數據的儲存的,開啟AOF模式後,所有存進redis內存的數據都會進入os cache中,然後默認1秒執行一次fsync寫入追加到appendonly.aof文件中。一般我們配置redis.conf中的一下指令:

AOF和RDB模式我們一般在生產環境都會打開,一般而言,redis服務掛掉後進行重啟會優先家在aof中的文件。

當啟動一個slave node的時候,它會發送一個PSYNC命令給master node,如果這是slave node重新連接master node,那麼master node僅僅會復制給slave部分缺少的數據;否則如果是slave node第一次連接master node,那麼會觸發一次full resynchronization;
開始full resynchronization的時候,master會啟動一個後台線程,開始生成一份RDB快照文件,同時還會將從客戶端收到的所有寫命令緩存在內存中。RDB文件生成完畢之後,master會將這個RDB發送給slave,slave會先寫入本地磁碟,然後再從本地磁碟載入到內存中。然後master會將內存中緩存的寫命令發送給slave,slave也會同步這些數據。
slave node如果跟master node有網路故障,斷開了連接,會自動重連。master如果發現有多個slave node都來重新連接,僅僅會啟動一個rdb save操作,用一份數據服務所有slave node。

從redis 2.8開始,就支持主從復制的斷點續傳,如果主從復制過程中,網路連接斷掉了,那麼可以接著上次復制的地方,繼續復制下去,而不是從頭開始復制一份。

master node會在內存中常見一個backlog,master和slave都會保存一個replica offset還有一個master id,offset就是保存在backlog中的。如果master和slave網路連接斷掉了,slave會讓master從上次的replica offset開始繼續復制,但是如果沒有找到對應的offset,那麼就會執行一次resynchronization。

master在內存中直接創建rdb,然後發送給slave,不會在自己本地落地磁碟了,可以有如下配置:

slave不會過期key,只會等待master過期key。如果master過期了一個key,或者通過LRU淘汰了一個key,那麼會模擬一條del命令發送給slave。

在redis.conf配置文件中,上面的參數代表至少需要3個slaves節點與master節點進行連接,並且master和每個slave的數據同步延遲不能超過10秒。一旦上面的設定沒有匹配上,則master不在提供相應的服務。

sdown達成的條件很簡單,如果一個哨兵ping一個master,超過了 is-master-down-after-milliseconds 指定的毫秒數之後,就主觀認為master宕機
sdown到odown轉換的條件很簡單,如果一個哨兵在指定時間內,收到了 quorum 指定數量的其他哨兵也認為那個master是sdown了,那麼就認為是odown了,客觀認為master宕機

如果一個slave跟master斷開連接已經超過了down-after-milliseconds的10倍,外加master宕機的時長,那麼slave就被認為不適合選舉為master

(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

每次一個哨兵要做主備切換,首先需要quorum數量的哨兵認為odown,然後選舉出一個slave來做切換,這個slave還得得到majority哨兵的授權,才能正式執行切換;

(2)SENTINEL RESET *,在所有sentinal上執行,清理所有的master狀態
(3)SENTINEL MASTER mastername,在所有sentinal上執行,查看所有sentinal對數量是否達成了一致

4.3.2 slave的永久下線

讓master摘除某個已經下線的slave:SENTINEL RESET mastername,在所有的哨兵上面執行.

redis的集群模式為了解決系統的橫向擴展以及海量數據的存儲問題,如果你的數據量很大,那麼就可以用redis cluster。
redis cluster可以支撐N個redis master,一個master上面可以掛載多個slave,一般情況我門掛載一個到兩個slave,master在掛掉以後會主動切換到slave上面,或者當一個master上面的slave都掛掉後,集群會從其他master上面找到冗餘的slave掛載到這個master上面,達到了系統的高可用性。

2.1 redis cluster的重要配置

2.2 在三台機器上啟動6個redis實例

將上面的配置文件,在/etc/redis下放6個,分別為: 7001.conf,7002.conf,7003.conf,7004.conf,7005.conf,7006.conf

每個啟動腳本內,都修改對應的埠號

2.3 創建集群

解決辦法是 先安裝rvm,再把ruby版本提升至2.3.3

使用redis-trib.rb命令創建集群

--replicas: 表示每個master有幾個slave

redis-trib.rb check 192.168.31.187:7001 查看狀體

3.1 加入新master

以上相同配置完成後,設置啟動腳本進行啟動;然後用如下命令進行node節點添加:

3.2 reshard一些數據過去

3.3 添加node作為slave

3.4 刪除node

㈤ Redis的LRU緩存淘汰演算法實現

LRU, 最近最少使用 (Least Recently Used,LRU),經典緩存演算法。

LRU會使用一個鏈表維護緩存中每個數據的訪問情況,並根據數據的實時訪問,調整數據在鏈表中的位置,然後通過數據在鏈表中的位置,表示數據是最近剛訪問的,還是已有段時間未訪問。

LRU會把鏈頭、尾分別設為MRU端和LRU端:

LRU可分成如下情況:

case2圖解:鏈表長度為5,從鏈表頭部到尾部保存的數據分別是5,33,9,10,8。假設數據9被訪問一次,則9就會被移動到鏈表頭部,同時,數據5和33都要向鏈表尾部移動一位。

所以若嚴格按LRU實現,假設Redis保存的數據較多,還要在代碼中實現:

最終導致降低Redis訪問性能。

所以,無論是為節省內存 or 保持Redis高性能,Redis並未嚴格按LRU基本原理實現,而是 提供了一個近似LRU演算法實現

Redis的內存淘汰機制是如何啟用近似LRU演算法的?redis.conf中的如下配置參數:

所以,一旦設定maxmemory選項,且將maxmemory-policy配為allkeys-lru或volatile-lru,近似LRU就被啟用。allkeys-lru和volatile-lru都會使用近似LRU淘汰數據,區別在於:

Redis如何實現近似LRU演算法的呢?

近似LRU演算法仍需區分不同數據的訪問時效性,即Redis需知道數據的最近一次訪問時間。因此,有了LRU時鍾:記錄數據每次訪問的時間戳。

Redis對每個KV對中的V,會使用個redisObject結構體保存指向V的指針。那redisObject除記錄值的指針,還會使用24 bits保存LRU時鍾信息,對應的是lru成員變數。這樣,每個KV對都會把它最近一次被訪問的時間戳,記錄在lru變數。

redisObject定義包含lru成員變數的定義:

每個KV對的LRU時鍾值是如何計算的?Redis Server使用一個實例級別的全局LRU時鍾,每個KV對的LRU time會根據全局LRU時鍾進行設置。

這全局LRU時鍾保存在Redis全局變數server的成員變數 lruclock

當Redis Server啟動後,調用initServerConfig初始化各項參數時,會調用getLRUClock設置lruclock的值:

於是,就得注意, 若一個數據前後兩次訪問的時間間隔 1s,那這兩次訪問的時間戳就是一樣的! 因為LRU時鍾精度就是1s,它無法區分間隔小於1秒的不同時間戳!

getLRUClock函數將獲得的UNIX時間戳,除以LRU_CLOCK_RESOLUTION後,就得到了以LRU時鍾精度來計算的UNIX時間戳,也就是當前的LRU時鍾值。

getLRUClock會把LRU時鍾值和宏定義LRU_CLOCK_MAX(LRU時鍾能表示的最大值)做與運算。

所以默認情況下,全局LRU時鍾值是以1s為精度計算得UNIX時間戳,且是在initServerConfig中進行的初始化。

那Redis Server運行過程中,全局LRU時鍾值是如何更新的?和Redis Server在事件驅動框架中,定期運行的時間事件所對應的serverCron有關。

serverCron作為時間事件的回調函數,本身會周期性執行,其頻率值由redis.conf的 hz配置項 決定,默認值10,即serverCron函數會每100ms(1s/10 = 100ms)運行一次。serverCron中,全局LRU時鍾值就會按該函數執行頻率,定期調用getLRUClock進行更新:

這樣,每個KV對就能從全局LRU時鍾獲取最新訪問時間戳。

對於每個KV對,它對應的redisObject.lru在哪些函數進行初始化和更新的呢?

對於一個KV對,其LRU時鍾值最初是在這KV對被創建時,進行初始化設置的,這初始化操作在 createObject函數 中調用,當Redis要創建一個KV對,就會調用該函數。

createObject除了會給redisObject分配內存空間,還會根據maxmemory_policy配置,初始化設置redisObject.lru。

LRU_CLOCK返回當前全局LRU時鍾值。因為一個KV對一旦被創建,就相當於有了次訪問,其對應LRU時鍾值就表示了它的訪問時間戳:

那一個KV對的LRU時鍾值又是何時再被更新?

只要一個KV對被訪問,其LRU時鍾值就會被更新!而當一個KV對被訪問時,訪問操作最終都會調用 lookupKey

lookupKey會從全局哈希表中查找要訪問的KV對。若該KV對存在,則lookupKey會根據maxmemory_policy的配置值,來更新鍵值對的LRU時鍾值,也就是它的訪問時間戳。

而當maxmemory_policy沒有配置為LFU策略時,lookupKey函數就會調用LRU_CLOCK函數,來獲取當前的全局LRU時鍾值,並將其賦值給鍵值對的redisObject結構體中的lru變數

這樣,每個KV對一旦被訪問,就能獲得最新的訪問時間戳。但你可能好奇:這些訪問時間戳最終是如何被用於近似LRU演算法進行數據淘汰的?

Redis之所以實現近似LRU,是為減少內存資源和操作時間上的開銷。

近似LRU主要邏輯在performEvictions。

performEvictions被evictionTimeProc調用,而evictionTimeProc函數又是被processCommand調用。

processCommand,Redis處理每個命令時都會調用:

然後,isSafeToPerformEvictions還會再次根據如下條件判斷是否繼續執行performEvictions:

一旦performEvictions被調用,且maxmemory-policy被設置為allkeys-lru或volatile-lru,近似LRU就被觸發執行了。

執行可分成如下步驟:

調用getMaxmemoryState評估當前內存使用情況,判斷當前Redis Server使用內存容量是否超過maxmemory配置值。

若未超過maxmemory ,則返回C_OK,performEvictions也會直接返回。

getMaxmemoryState評估當前內存使用情況的時候,若發現已用內存超出maxmemory,會計算需釋放的內存量。這個釋放內存大小=已使用內存量-maxmemory。

但已使用內存量並不包括用於主從復制的復制緩沖區大小,這是getMaxmemoryState通過調用freeMemoryGetNotCountedMemory計算的。

而若當前Server使用的內存量超出maxmemory上限 ,則performEvictions會執行while循環淘汰數據釋放內存。

為淘汰數據,Redis定義數組EvictionPoolLRU,保存待淘汰的候選KV對,元素類型是evictionPoolEntry結構體,保存了待淘汰KV對的空閑時間idle、對應K等信息:

這樣,Redis Server在執行initSever進行初始化時,會調用evictionPoolAlloc為EvictionPoolLRU數組分配內存空間,該數組大小由EVPOOL_SIZE決定,默認可保存16個待淘汰的候選KV對。

performEvictions在淘汰數據的循環流程中,就會更新這個待淘汰的候選KV對集合,即EvictionPoolLRU數組。

performEvictions調用evictionPoolPopulate,其會先調用dictGetSomeKeys,從待采樣哈希表隨機獲取一定數量K:

於是,dictGetSomeKeys返回採樣的KV對集合。evictionPoolPopulate根據實際采樣到的KV對數量count,執行循環:調用estimateObjectIdleTime計算在采樣集合中的每一個KV對的空閑時間:

接著,evictionPoolPopulate遍歷待淘汰的候選KV對集合,即EvictionPoolLRU數組,嘗試把采樣的每個KV對插入EvictionPoolLRU數組,取決於如下條件之一:

有一成立,evictionPoolPopulate就能把采樣KV對插入EvictionPoolLRU數組。等所有采樣鍵值對都處理完後,evictionPoolPopulate函數就完成對待淘汰候選鍵值對集合的更新了。

接下來,performEvictions開始選擇最終被淘汰的KV對。

因evictionPoolPopulate已更新EvictionPoolLRU數組,且該數組里的K,是按空閑時間從小到大排好序了。所以,performEvictions遍歷一次EvictionPoolLRU數組,從數組的最後一個K開始選擇,若選到的K非空,就把它作為最終淘汰的K。

該過程執行邏輯:

一旦選到被淘汰的K,performEvictions就會根據Redis server的惰性刪除配置,執行同步刪除或非同步刪除:

至此,performEvictions就淘汰了一個K。若此時釋放的內存空間還不夠,即沒有達到待釋放空間,則performEvictions還會 重復執行 前面所說的更新待淘汰候選KV對集合、選擇最終淘汰K的過程,直到滿足待釋放空間的大小要求。

performEvictions流程:

近似LRU演算法並未使用耗時且耗空間的鏈表,而使用 固定大小的待淘汰數據集合 ,每次隨機選擇一些K加入待淘汰數據集合。

最後,按待淘汰集合中K的空閑時間長度,刪除空閑時間最長的K。

根據LRU演算法的基本原理,發現若嚴格按基本原理實現LRU演算法,則開發的系統就需要額外內存空間保存LRU鏈表,系統運行時也會受到LRU鏈表操作的開銷影響。

而Redis的內存資源和性能都很重要,所以Redis實現近似LRU演算法:

一個演算法的基本原理和演算法的實際執行,在系統開發中會有一定折中,需綜合考慮所開發的系統,在資源和性能方面的要求,以避免嚴格按照演算法實現帶來的資源和性能開銷。

㈥ Redis分布式緩存搭建

花了兩天時間整理了之前記錄的Redis單體與哨兵模式的搭建與使用,又補齊了集群模式的使用和搭建經驗,並對集群的一些個原理做了理解。

筆者安裝中遇到的一些問題:

如果make報錯,可能是沒裝gcc或者gcc++編輯器,安裝之 yum -y install gcc gcc-c++ kernel-devel ,有可能還是提示一些個c文件編譯不過,gcc -v查看下版本,如果不到5.3那麼升級一下gcc:

在 /etc/profile 追加一行 source /opt/rh/devtoolset-9/enable

scl enable devtoolset-9 bash

重新make clean, make

這回編譯通過了,提示讓你最好make test一下/

執行make test ,如果提示 You need tcl 8.5 or newer in order to run the Redis test

那就升級tcl, yum install tcl

重新make test,如果還有error就刪了目錄,重新tar包解壓重新make , make test

o/ All tests passed without errors! ,表示編譯成功。

然後make install即可。

直接運行命令: ./redis-server /usr/redis-6.0.3/redis.conf &

redis.conf 配置文件里 bind 0.0.0.0 設置外部訪問, requirepass xxxx 設置密碼

redis高可用方案有兩種:

常用搭建方案為1主1從或1主2從+3哨兵監控主節點, 以及3主3從6節點集群。

(1)sentinel哨兵

/usr/redis-6.0.3/src/redis-sentinel /usr/redis-6.0.3/sentinel2.conf &

sentinel2.conf配置:

坑1:master節點也會在故障轉移後成為從節點,也需要配置masterauth

當kill master進程之後,經過sentinel選舉,slave成為了新的master,再次啟動原master,提示如下錯誤:

原因是此時的master再次啟動已經是slave了,需要向現在的新master輸入密碼,所以需要在master.conf
中配置:

坑2:哨兵配置文件要暴露客戶端可以訪問到的master地址

在 sentinel.conf 配置文件的 sentinel monitor mymaster 122.xx.xxx.xxx 6379 2 中,配置該哨兵對應的master名字、master地址和埠,以及達到多少個哨兵選舉通過認為master掛掉。其中master地址要站在redis訪問者(也就是客戶端)的角度、配置訪問者能訪問的地址,例如sentinel與master在一台伺服器(122.xx.xxx.xxx)上,那麼相對sentinel其master在本機也就是127.0.0.1上,這樣 sentinel monitor mymaster 127.0.0.1 6379 2 邏輯上沒有問題,但是如果另外伺服器上的springboot通過lettuce訪問這個redis哨兵,則得到的master地址為127.0.0.1,也就是springboot所在伺服器本機,這顯然就有問題了。

附springboot2.1 redis哨兵配置:

坑3:要注意配置文件.conf會被哨兵修改

redis-cli -h localhost -p 26379 ,可以登到sentinel上用info命令查看一下哨兵的信息。

曾經遇到過這樣一個問題,大致的信息如下

slaves莫名其妙多了一個,master的地址也明明改了真實對外的地址,這里又變成127.0.0.1 !
最後,把5個redis進程都停掉,逐個檢查配置文件,發現redis的配置文件在主從哨兵模式會被修改,master的配置文件最後邊莫名其妙多了一行replicaof 127.0.0.1 7001, 懷疑應該是之前配置錯誤的時候(見坑2)被哨兵動態加上去的! 總之,實踐中一定要多注意配置文件的變化。

(2)集群

當數據量大到一定程度,比如幾十上百G,哨兵模式不夠用了需要做水平拆分,早些年是使用codis,twemproxy這些第三方中間件來做分片的,即 客戶端 -> 中間件 -> Redis server 這樣的模式,中間件使用一致性Hash演算法來確定key在哪個分片上。後來Redis官方提供了方案,大家就都採用官方的Redis Cluster方案了。

Redis Cluster從邏輯上分16384個hash slot,分片演算法是 CRC16(key) mod 16384 得到key應該對應哪個slot,據此判斷這個slot屬於哪個節點。

每個節點可以設置1或多個從節點,常用的是3主節點3從節點的方案。

reshard,重新分片,可以指定從哪幾個節點移動一些hash槽到另一個節點去。重新分片的過程對客戶端透明,不影響線上業務。

搭建Redis cluster

redis.conf文件關鍵的幾個配置:

啟動6個集群節點

[root@VM_0_11_centos redis-6.0.3]# ps -ef|grep redis
root 5508 1 0 21:25 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7001 [cluster]
root 6903 1 0 21:32 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7002 [cluster]
root 6939 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7003 [cluster]
root 6966 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7004 [cluster]
root 6993 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7005 [cluster]
root 7015 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7006 [cluster]

這時候這6個節點還是獨立的,要把他們配置成集群:

說明: -a xxxx 是因為筆者在redis.conf中配置了requirepass xxxx密碼,然後 --cluster-replicas 1 中的1表示每個master節點有1個從節點。

上述命令執行完以後會有一個詢問: Can I set the above configuration? yes同意自動做好的分片即可。

最後 All 16384 slots covered. 表示集群中16384個slot中的每一個都有至少有1個master節點在處理,集群啟動成功。

查看集群狀態:

坑1:暴露給客戶端的節點地址不對

使用lettuce連接發現連不上,查看日誌 Connection refused: no further information: /127.0.0.1:7002 ,跟之前哨兵配置文件sentinel.conf里邊配置master地址犯的錯誤一樣,集群啟動的時候帶的地址應該是提供給客戶端訪問的地址。

我們要重建集群:先把6個redis進程停掉,然後刪除 nodes-7001.conf 這些節點配置文件,刪除持久化文件 mp.rdb 、 appendonly.aof ,重新啟動6個進程,在重新建立集群:

然後,還是連不上,這次報錯 connection timed out: /172.xx.0.xx:7004 ,發現連到企鵝雲伺服器的內網地址上了!

解決辦法,修改每個節點的redis.conf配置文件,找到如下說明:

所以增加配置:

然後再重新構建集群,停進程、改配置、刪除節點文件和持久化文件、啟動進程、配置集群。。。再來一套(累死了)

重新使用Lettuce測試,這次終於連上了!

坑2:Lettuce客戶端在master節點故障時沒有自動切換到從節點

name這個key在7002上,kill這個進程模擬master下線,然後Lettuce一直重連。我們期望的是應該能自動切換到其slave 7006上去,如下圖:

重新啟動7002進程,

7006已成為新master,7002成為它的slave,然後Lettuce也能連接上了。
解決辦法,修改Lettuce的配置:

筆者用的是springboot 2.1 spring-boot-starter-data-redis 默認的Lettuce客戶端,當使用Redis cluster集群模式時,需要配置一下 RedisConnectionFactory 開啟自適應刷新來做故障轉移時的自動切換從節點進行連接。

重新測試:停掉master 7006,這次Lettuce可以正常切換連到7002slave上去了。(仍然會不斷的在日誌里報連接錯誤,因為需要一直嘗試重連7006,但因為有7002從節點頂上了、所以應用是可以正常使用的)

Redis不保證數據的強一致性

Redis並不保證數據的強一致性,也就是取CAP定理中的AP

關於一致性Hash演算法,可以參考 一致性Hash演算法 - (jianshu.com)

Redis cluster使用的是hash slot演算法,跟一致性Hash演算法不太一樣,固定16384個hash槽,然後計算key落在哪個slot里邊(計算key的CRC16值再對16384取模),key找的是slot而不是節點,而slot與節點的對應關系可以通過reshard改變並通過gossip協議擴散到集群中的每一個節點、進而可以為客戶端獲知,這樣key的節點定址就跟具體的節點個數沒關系了。也同樣解決了普通hash取模演算法當節點個數發生變化時,大量key對應的定址都發生改動導致緩存失效的問題。

比如集群增加了1個節點,這時候如果不做任何操作,那麼新增加的這個節點上是沒有slot的,所有slot都在原來的節點上且對應關系不變、所以沒有因為節點個數變動而緩存失效,當reshard一部分slot到新節點後,客戶端獲取到新遷移的這部分slot與新節點的對應關系、定址到新節點,而沒遷移的slot仍然定址到原來的節點。

關於熱遷移,猜想,內部應該是先做復制遷移,等遷移完了,再切換slot與節點的對應關系,復制沒有完成之前仍按照原來的slot與節點對應關系去原節點訪問。復制結束之後,再刪除原節點上已經遷移的slot所對應的key。

與哨兵模式比較類似,當1個節點發現某個master節點故障了、會對這個故障節點進行pfail主觀宕機,然後會通過gossip協議通知到集群中的其他節點、其他節點也執行判斷pfail並gossip擴散廣播這一過程,當超過半數節點pfail時那麼故障節點就是fail客觀宕機。接下來所有的master節點會在故障節點的從節點中選出一個新的主節點,此時所有的master節點中超過半數的都投票選舉了故障節點的某個從節點,那麼這個從節點當選新的master節點。

所有節點都持有元數據,節點之間通過gossip這種二進制協議進行通信、發送自己的元數據信息給其他節點、故障檢測、集群配置更新、故障轉移授權等等。

這種去中心化的分布式節點之間內部協調,包括故障識別、故障轉移、選主等等,核心在於gossip擴散協議,能夠支撐這樣的廣播協議在於所有的節點都持有一份完整的集群元數據,即所有的節點都知悉當前集群全局的情況。

Redis高可用方案 - (jianshu.com)

面試題:Redis 集群模式的工作原理能說一下么 - 雲+社區 - 騰訊雲 (tencent.com)

深度圖解Redis Cluster原理 - detectiveHLH - 博客園 (cnblogs.com)

Redis學習筆記之集群重啟和遇到的坑-阿里雲開發者社區 (aliyun.com)

雲伺服器Redis集群部署及客戶端通過公網IP連接問題

㈦ 如何使用 Azure Redis 緩存

1.功能 Redis 是一種高級的鍵值存儲,其中,鍵可以包含數據結構,例如字元串、哈希、列表、集合和有序集合。Redis 支持針對這些數據類型的一組原子操作。 Redis 還支持設置簡單的主-從復制,具有非常快的非首先阻止同步、網路分割時自動重新連接等。 其他功能包括事務、發布/訂閱、Lua 腳本、具有有限生存時間的鍵和配置設置,使 Redis 在行為上與緩存類似。 您可以通過當今最常用編程語言使用 Redis。 Azure Redis 緩存利用 Redis 身份驗證並且還支持與 Redis 的 SSL 連接。 2.可復用黃色別墅 相比筆者之前寫的文檔: Windows Azure Cloud Service (44) 使用Azure In-Role Cache緩存(1)Co-located Role Windows Azure Cloud Service (45) 使用Azure In-Role Cache緩存(2)Dedicated Role 以上的In-Role Cache只會被部署的Cloud Service獨享的,如果新創建的其他Cloud Service Project想共享是無法實現的。 我們通過創建Azure Redis Cache以後,這個Redis Cache就是共享的,一個或者多個Azure Application就可以同時使用這個Azure Redis Cache 3.服務級別 Microsoft Azure Redis Cache分為兩個級別: (1)基本(Basic) - 單個節點。提供不同的大小。基本模式是沒有SLA的。 (2)標准(Standard) - 雙節點,主從模式。包括SLA和支持復制。提供多種大小。326電影網 (3)高級(Premium) - 企業級緩存服務。專為大規模並發設計。 Azure Redis Cache提供以下不同的服務級別: 基本(Basic,不包含SLA): 緩存名稱 緩存大小 網路性能 客戶端連接數 C0 250MB 低 256 C1 1GB 低 1000 C2 2.5GB 中等 2000 C3 6GB 中等性喜劇 5000 C4 13GB 中等 10000 C5 26GB 高 15000 C6 53GB 最高 20000 標准(Standard,支持SLA): 緩存名稱 緩存大小 網路性能 客戶端連接數 C0 250MB 低 256 C1 1GB 低 1000 C2 2.5GB 中等 2000 C3 6GB 中等 5000 C4 13GB 中等 10000 C5 26GB 高 15000 C6 53GB 最高 20000 高級(Premium): 緩存名稱 緩存大小 網路性能 客戶端連接數量 P1 6GB 中等 7500 P2 13GB 中等 15000 P3 26GB 高 30000 P4 53GB 最高 40000 326影視 4.高性能 Azure Redis 緩存幫助您的應用程序變得更具響應性(甚至在用戶負載增加時也如此),以及利用 Redis 引擎的低延遲、高吞吐量功能。此單獨的分布式緩存層允許數據層獨立擴展以便更高效地利用應用程序層中的計算資源。

㈧ redis常見問題

1. 緩存擊穿

緩存擊穿是指一個請求要訪問的數據,緩存中沒有,但資料庫中有的情況。這種情況一般都是緩存過期了。

但是這時由於並發訪問這個緩存的用戶特別多,這是一個熱點 key,這么多用戶的請求同時過來,在緩存裡面沒有取到數據,所以又同時去訪問資料庫取數據,引起資料庫流量激增,壓力瞬間增大,直接崩潰給你看。

所以一個數據有緩存,每次請求都從緩存中快速的返回了數據,但是某個時間點緩存失效了,某個請求在緩存中沒有請求到數據,這時候我們就說這個請求就"擊穿"了緩存。

針對這個場景,對應的解決方案一般來說有三種。

藉助Redis setNX命令設置一個標志位就行。設置成功的放行,設置失敗的就輪詢等待。就是在更新緩存時加把鎖

後台開一個定時任務,專門主動更新過期數據

比如程序中設置 why 這個熱點 key 的時候,同時設置了過期時間為 10 分鍾,那後台程序在第 8 分鍾的時候,會去資料庫查詢數據並重新放到緩存中,同時再次設置緩存為 10 分鍾。

其實上面的後台續命思想的最終體現是也是永不過期。

只是後台續命的思想,會主動更新緩存,適用於緩存會變的場景。會出現緩存不一致的情況,取決於你的業務場景能接受多長時間的緩存不一致。


2. 緩存穿透

緩存穿透是指一個請求要訪問的數據,緩存和資料庫中都沒有,而用戶短時間、高密度的發起這樣的請求,每次都打到資料庫服務上,給資料庫造成了壓力。一般來說這樣的請求屬於惡意請求。

解決方案有兩種:

就是在資料庫即使沒有查詢到數據,我們也把這次請求當做 key 緩存起來,value 可以是 NULL。下次同樣請求就會命中這個 NULL,緩存層就處理了這個請求,不會對資料庫產生壓力。這樣實現起來簡單,開發成本很低。


3. 緩存雪崩

緩存雪崩是指緩存中大多數的數據在同一時間到達過期時間,而查詢數據量巨大,這時候,又是緩存中沒有,資料庫中有的情況了。

防止雪崩的方案簡單來說就是錯峰過期。

在設置 key 過期時間的時候,在加上一個短的隨機過期時間,這樣就能避免大量緩存在同一時間過期,引起的緩存雪崩。

如果發了雪崩,我們可以有服務降級、熔斷、限流手段來拒絕一些請求,保證服務的正常。但是,這些對用戶體驗是有一定影響的。

4. Redis 高可用架構

Redis 高可用架構,大家基本上都能想到主從、哨兵、集群這三種模式。

哨兵模式:

它主要執行三種類型的任務:

哨兵其實也是一個分布式系統,我們可以運行多個哨兵。

然後這些哨兵之間需要相互通氣,交流信息,通過投票來決定是否執行自動故障遷移,以及選擇哪個從伺服器作為新的主伺服器。

哨兵之間採用的協議是 gossip,是一種去中心化的協議,達成的是最終一致性。

選舉規則:

㈨ redis做緩存,怎麼取出全部key

redis做緩存的時候,怎麼取出全部相同前綴的key,網路到很多都是keys,scan
獲取當前庫下的所有key
可以使用 keys * 命令,keys支持模糊匹配,但是cpu使用率有點高。還有一種就是scan命令

設置一個set,在緩存的時候把數據的key存到這個set裡面

php 分頁查詢怎麼redis緩存

對於有分頁條件的緩存,我們也可以按照不同的分頁條件來緩存多個key,比如分頁查詢產品列表,page=1&limit=10和page=1&limit=5這兩次請求可以這樣緩存查詢結果

proctList:page:1:limit:10

proctList:page:1:limit:5
這個是一種常見方案,但是存在著一些問題:

緩存的value存在冗餘,proctList:page:1:limit:10緩存的內容其實是包括了proctList:page:1:limit:5中的內容(緩存兩個key的時候,數據未發生變化的情況下)

僅僅是改變了查詢條件的分頁條件,就會導致緩存未命中,降低了緩存的命中率

為了保證數據一致性,需要清理緩存的時候,很難處理,redis的keys命令對性能影響很大,會導致redis很大的延遲,生產環境一般來說禁止該命令。自己手動拼緩存key,你可能根本不知道拼到哪一個page為止。

放棄數據一致性,通過設置失效時間來自動失效,可能會出現查詢第一頁命中了緩存,查詢第二頁的時候未命中緩存,但此時數據已經發生了改變,導致第二頁查詢返回的和第一頁相同的結果。
以上,在分頁條件下這樣使用常規方案總感覺有諸多困擾,諸多麻煩,那是不是就應該放棄使用緩存?
基於SortedSet的分頁查詢緩存方案
首先想到的解決方法是使用@see ListOperations<K, V>不再根據分頁條件使用多個key,而是使用一個key,也不分頁將全部的數據緩存到redis中,然後按照分頁條件使用range(key,start,limit)獲取分頁的結果,這個會導致一個問題,當緩存失效時,並發的寫緩存會導致出現重復數據
所以想到通過使用set來處理並發時的重復數據,@see ZSetOperations<K, V>
代碼邏輯如下:

range(key,start,limit)按照分頁條件獲取緩存,命中則直接返回

緩存未命中,查詢(沒有分頁條件)資料庫或是調用(沒有分頁)底層介面

add(key,valueScoreMap<value,score>)寫入緩存,expire設置緩存時間

當需要清理緩存時,直接刪除key,如果是因為數據新增和刪除,可以add(key,value,score)或remove(key,value)

redis中會按照score分值升序排列map中的數據,一般的,score分值是sql語句的order by filedA的filedA的值,這樣能保證數據一致性
但是這種方式也存在一定問題:

這個key緩存的value確實是熱數據,但可能只有少數數據被頻繁使用其餘的可能根本就未被使用,比如數據有100頁,實際可能只會用到前10頁,這也會導致緩存空間的浪費,如果使用了redis虛擬內存,也會有一定影響

sql查詢由原來的分頁查詢變成了不分頁查詢,緩存失效後,系統的處理能力較之前會有下降,尤其是對於大表.

熱點內容
vivo手機為什麼不能設置鎖屏密碼 發布:2025-08-02 13:52:05 瀏覽:644
php二進制加密 發布:2025-08-02 13:51:04 瀏覽:279
水強行壓縮 發布:2025-08-02 13:37:23 瀏覽:988
nginx內網訪問 發布:2025-08-02 13:35:06 瀏覽:31
如何用解壓密碼解壓手機文件 發布:2025-08-02 13:32:56 瀏覽:217
lex製作編譯器 發布:2025-08-02 13:31:52 瀏覽:5
php把數組寫入文件 發布:2025-08-02 13:25:51 瀏覽:280
網頁升級訪問狼 發布:2025-08-02 13:20:37 瀏覽:753
雲頂之弈決斗壓縮陣容 發布:2025-08-02 13:08:59 瀏覽:555
爆點演算法 發布:2025-08-02 13:01:49 瀏覽:648