日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

redis的主從復制,哨兵和cluster集群

作者:宋回嘉樂嗎 更新時間: 2022-11-29 編程語言

一、redis性能管理

(1) redis-cli
?127.0.0.1:6379> info memory
??
?
?(2) redis-cli info memory

  • used_memory_rss:是Redis向操作系統申請的內存。
  • used_memory:是Redis中的數據占用的內存。
  • used_memory_peak:redis內存使用的峰值。

1.2內存碎片

內存碎片率=Redis向操作系統申請的內存 / Redis中的數據占用的內存

mem_fragmentation_ratio = used_memory_rss / used_memory

mem_fragmentation_ratio:內存碎片率。

redis-cli info memory |grep ratio
?

內存碎片產生的原因

  • Redis內部有自已的內存管理器,為了提高內存使用的效率,來對內存的申請和釋放進行管理。
  • Redis中的值刪除的時候,并沒有把內存直接釋放、交還給操作系統,而是交給了Redis內部有內存管理器。
  • Redis中申請內存的時候,也是先看自己的內存管理器中是否有足夠的內存可用。
  • Redis的這種機制,提高了內存的使用率,但是會使Redis中有部分自己沒在用,卻不釋放的內存,導致了內存碎片的發生。

內存碎片率對redis的影響?

  • 內存碎片率在1到1.5之間是正常的,這個值表示內存碎片率比較低,也說明Redis 沒有發生內存交換。
  • 內存碎片率超過1.5,說明Redis消耗了實際需要的物理內存的150%,其中50%是內存碎片率。
  • 內存碎片率低于1的,說明Redis內存分配超出了物理內存,操作系統正在進行內存交換(使用虛擬內存,會降低性能)。需要增加可用物理內存或減少Redis內存占用。

解決碎片率過大的方法?

  • 如果你的Redis版本是4.0以下的,需要在redis-cli 工具上輸入shutdown save命令,讓Redis數據庫執行保存操作并關閉Redis服務,再重啟服務器。Redis服務器重啟后,Redis 會將沒用的內存歸還給操作系統,碎片率會降下來。
  • Redis4.0版本開始,可以在不重啟的情況下,線上整理內存碎片,將未使用的內存歸還給操作系統。

?config set activedefrag yes ? ?#自動碎片清理
?memory purge ? ? ? ? ? ? ? ? ? #手動碎片清理

?1.3內存使用率?

redis實例的內存使用率超過可用最大內存,操作系統將開始進行內存與swap空間交換。

避免內存交換發生的方法:

  • 針對緩存數據大小選擇安裝Redis 實例
  • 盡可能的使用Hash數據結構存儲
  • 設置key的過期時間

1.4內回收key?

存清理策略,保證合理分配redis有限的內存資源。

當內存使用達到設置的最大閾值時,需選擇一種key的回收策略,默認情況下回收策略是禁止刪除(noenviction)。配置文件中修改 maxmemory-policy 屬性值:

im /etc/redis/6379.conf
?---598行----
?maxmemory-policy noenviction ? #修改max-memory-policy屬性值
??
?##回收策略有以下幾種:##
?●volatile-lru
?#使用LRU算法從已設置過期時間的數據集合中淘汰數據
?(移除最近最少使用的key,針對設置了TTL的key)
??
?●volatile-ttl
?#從已設置過期時間的數據集合中挑選即將過期的數據淘汰
?(移除最近過期的key)
??
?●volatile-random
?#從已設置過期時間的數據集合中隨機挑選數據淘汰
?(在設置了TTL的key里隨機移除)
??
?●allkeys-lru
?#使用LRU算法 從所有數據集合中淘汰數據
?(移除最少使用的key,針對所有的key)
??
?●allkeys-random
?#從數據集合中任意選擇數據淘汰(隨機移除key)
??
?●noenviction
?#禁止淘汰數據(不刪除直到寫滿時報錯)

二、redis的優化策略

2.1設置Redis客戶端連接的超時時間?

vim /etc/redis/6379.conf
?-----114行------
?114 timeout 0 ? ??
?#單位為秒(s),取值范圍為0~100000。默認值為0,表示無限制,即Redis不會主動斷開連接,即使這個客戶端已經空閑了很長時間。
?#例如可設置為600,則客戶端空閑10分鐘后,Redis會主動斷開連接。
??
?#注意:在實際運行中,為了提高性能,Redis不一定會精確地按照timeout的值規定的時間來斷開符合條件的空閑連接,例如設置timeout為10s,但空閑連接可能在12s后,服務器中新增很多連接時才會被斷開。

2.2?設置redis自動碎片清理

?config set activedefrag yes ? ?#自動碎片清理
?memory purge ? ? ? ? ? ? ? ? ? #手動碎片清理

2.3設置redis最大內存閾值?

內存閾值如果不設置,則沒有限制,直到把服務器的內存干滿、之后會使用交換分區。

設置內存閾值后,不會使用swap交換分區。且如果設置了key回收策略,當內存使用達到設置的最大閾值時,系統會進行key回收。

vim /etc/redis/6379.conf
?-----567行------
?567 # maxmemory <bytes>
?568 maxmemory 1gb ? ? ? ? ? #例如設置最大內存閾值為1gb

三、redis雪崩、穿透、擊穿的原因和解決方案

(1) redis雪崩

定義:緩存雪崩是指大量的應用請求無法在 Redis 緩存中進行處理,緊接著,應用將大量請求發送到數據庫層,導致數據庫層的壓力激增。?

一個簡單的雪崩過程:

  1. Redis 集群產生了大面積故障;

  2. 緩存失敗,此時仍有大量請求去訪問 Redis 緩存服務器;

  3. 在大量 Redis 請求失敗后,這些請求將會去訪問數據庫;

  4. 由于應用的設計依賴于數據庫和 Redis 服務,很快就會造成服務器集群的雪崩,最終導致整個系統的癱瘓。

?產生的原因:

1)緩存中有大量數據同時過期,導致大量請求無法得到處理。

2)Redis 緩存實例發生故障宕機了

解決方案:?

  • 【事前】高可用緩存:高可用緩存是防止出現整個緩存故障。即使個別節點,機器甚至機房都關閉,系統仍然可以提供服務,Redis 哨兵(Sentinel) 和 Redis 集群(Cluster) 都可以做到高可用;

  • 【事中】緩存降級(臨時支持):當訪問次數急劇增加導致服務出現問題時,我們如何確保服務仍然可用。在國內使用比較多的是 Hystrix,它通過熔斷、降級、限流三個手段來降低雪崩發生后的損失。只要確保數據庫不死,系統總可以響應請求,每年的春節 12306 我們不都是這么過來的嗎?只要還可以響應起碼還有搶到票的機會;

  • 【事后】Redis備份和快速預熱:Redis數據備份和恢復、快速緩存預熱。

(2)redis 擊穿

?緩存擊穿是指當前熱點數據存儲到期時,多個線程同時并發訪問熱點數據。因為緩存剛過期,所有并發請求都會到數據庫中查詢數據。

解決方法:

  • 將熱點數據設置為永不過期;

  • 加互斥鎖:互斥鎖可以控制查詢數據庫的線程訪問,但這種方案會導致系統的吞吐量下降,需要根據實際情況使用。

?(3)緩存穿透

緩存穿透是指緩存和數據庫中都沒有的數據,而用戶不斷發起請求,如發起id為-1的數據或者特別大的不存在的數據。有可能是黑客利用漏洞攻擊從而去壓垮應用的數據庫。?

  • 驗證攔截:接口層進行校驗,如鑒定用戶權限,對ID之類的字段做基礎的校驗,如id<=0的字段直接攔截;
  • 緩存空數據:當數據庫查詢到的數據為空時,也將這條數據進行緩存,但緩存的有效性設置得要較短,以免影響正常數據的緩存;
  • ?使用布隆過濾器:布隆過濾器是一種比較獨特數據結構,有一定的誤差。當它指定一個數據存在時,它不一定存在,但是當它指定一個數據不存在時,那么它一定是不存在的。

二、redis的高可用的概念

在web服務器中,高可用是指服務器可以正常訪問的時間,衡量的標準是在多長時間內可以提供正常服務(99.9%、99.99%、99.999%等等)。

高可用的計算公式是1-(宕機時間)/(宕機時間+運行時間)有點類似與網絡傳輸的參數誤碼率,我們用9的個數表示可用性:

2個9:99%,一年內宕機時長:1%×365天=3.6524天=87.6h

4個9:99.99%,一年內宕機時長:0.01%×365天=52.56min

5個9:99.999%,一年內宕機時長:0.001%*365天=5.265min

11個9:幾乎一年宕機時間只有幾秒鐘

但是在Redis語境中,高可用的含義似乎要寬泛一些,除了保證提供正常服務(如主從分離、快速容災技術),還需要考慮數據容量的擴展、數據安全不會丟失等

2.1Redis的高可用技術

在Redis中,實現高可用的技術主要包括持久化、主從復制、哨兵和cluster集群,下面分別說明它們的作用,以及解決了什么樣的問題。

  • 持久化:?持久化是最簡單的高可用方法(有時甚至不被歸為高可用的手段),主要作用是數據備份,即將數據存儲在硬盤,保證數據不會因進程退出而丟失。

  • 主從復制:?主從復制是高可用Redis的基礎,哨兵和集群都是在主從復制基礎上實現高可用的。主從復制主要實現了數據的多機備份(和同步),以及對于讀操作的負載均衡和簡單的故障恢復。

    • 缺陷:故障恢復無法自動化;寫操作無法負載均衡;存儲能力受到單機的限制。
  • 哨兵:?在主從復制的基礎上,哨兵實現了自動化的故障恢復。(主掛了,找一個從成為新的主,哨兵節點進行監控)

    • 缺陷:寫操作無法負載均衡;存儲能力受到單機的限制。
  • Cluster集群:?通過集群,Redis解決了寫操作無法負載均衡,以及存儲能力受到單機限制的問題,實現了較為完善的高可用方案。(6臺起步,成雙成對,3主3從)

三、redis主從復制

主從復制,是指將一臺Redis服務器的數據,復制到其他的Redis服務器。前者稱為主節點(Master),后者稱為從節點(slave);數據的復制是單向的,只能由主節點到從節點。

默認情況下,每臺Redis服務器都是主節點;且一個主節點可以有多個從節點(或沒有從節點),但一個從節點只能有一個主節點。

3.1主從復制的作用

  • 據冗余:?主從復制實現了數據的熱備份,是持久化之外的一種數據冗余方式。
  • 故障恢復:?當主節點出現問題時,可以由從節點提供服務,實現快速的故障恢復;實際上是一種服務的冗余。
  • 負載均衡:?在主從復制的基礎上,配合讀寫分離,可以由主節點提供寫服務,由從節點提供讀服務(即寫Redis數據時應用連接主節點,讀Redis數據時應用連接從節點),分擔服務器負載;尤其是在寫少讀多的場景下,通過多個從節點分擔讀負載,可以大大提高Redis服務器的并發量。
  • 高可用基石:?除了上述作用以外,主從復制還是哨兵和集群能夠實施的基礎,因此說主從復制是Redis高可用的基礎。

3.2主從復制流程

1)若啟動一個slave機器進程,則它會向Master機器發送一個sync command命令,請求同步連接。

(2)無論是第一次連接還是重新、【】連接,Master機器都會啟動一個后臺進程,將數據快照保存到數據文件中(執行rdb操作),同時Master還會記錄修改數據的所有命令并緩存在數據文件中.

(3)后臺進程完成緩存操作之后,Master機器就會向slave機器發送數據文件,slave端機器將數據文件保存到硬盤上,然后將其加載到內存中,接著Master機器就會將修改數據的所有操作一并發送給slave端機器。若slave出現故障導致宕機,則恢復正常后會自動重新連接。

(4)Master機器收到slave端機器的連接后,將其完整的數據文件發送給slave端機器,如果Mater同時收到多個slave發來的同步請求,則Master會在后臺啟動一個進程以保存數據文件,然后將其發送給所有的slave端機器,確保所有的slave端機器都正常。

四、redis一主二從的部署

實驗組件

主從 redis的版本號 IP地址
master redis-5.0.7 192.168.195.100
slave1 redis-5.0.7 192.168.195.200
slave2 redis-5.0.7 192.168.195.101

實驗具體步驟?

?實驗前準備好三臺源碼編譯安裝好的redis虛擬機

步驟一:修改master節點的配置文件?

vim /etc/redis/6379.conf?
?bind 0.0.0.0 ? ? ? ? ? ? ? ? ? ? ?#70行,修改監聽地址為0.0.0.0(生產環境中,尤其是多網卡最好填寫物理網卡的IP)
?daemonize yes ? ? ? ? ? ? ? ? ? ? #137行,開啟守護進程,后臺啟動?
?logfile /var/log/redis_6379.log ? #172行,指定日志文件存放目錄
?dir /var/lib/redis/6379 ? ? ? ? ? #264行,指定工作目錄
?appendonly yes ? ? ? ? ? ? ? ? ? ?#700行,開啟AOF持久化功能
?
/etc/init.d/redis_6379 restart ? ? #重啟redis服務

?

步驟二:修改slave節點的配置文件

#修改slave1的配置文件
vim /etc/redis/6379.conf?
?bind 0.0.0.0 ? ? ? ? ? ? ? ? ? ? ? ?#70行,修改監聽地址為0.0.0.0(生產環境中需要填寫物理網卡的IP)
?daemonize yes ? ? ? ? ? ? ? ? ? ? ? #137行,開啟守護進程,后臺啟動
?logfile /var/log/redis_6379.log ? ? #172行,指定日志文件目錄
?dir /var/lib/redis/6379 ? ? ? ? ? ? #264行,指定工作目錄
?replicaof 192.168.73.105 6379 ? ? ? #288行,指定要同步的Master節點的IP和端口
?appendonly yes ? ? ? ? ? ? ? ? ? ? ?#700行,修改為yes,開啟AOF持久化功能
?
#將配置文件傳給slave2
scp /etc/redis/6379.conf 192.168.73.107:/etc/redis/
?
/etc/init.d/redis_6379 restart ?#重啟redis
netstat -natp | grep redis ? ? ?#查看主從服務器是否已建立連接

實驗測試?

master寫入數據?

127.0.0.1:6379> keys *
?
127.0.0.1:6379> set name zhangsan
?
127.0.0.1:6379> get name

?從節點查詢 沒有問題

?五、Redis哨兵模式

主從切換技術的方法是:當服務器宕機后,需要手動一臺從機切換為主機,這需要人工干預,不僅費時費力而且還會造成一段時間內服務不可用。為了解決主從復制的缺點,就有了哨兵機制。

?哨兵的核心功能:在主從復制的基礎上,哨兵引入了主節點的自動故障轉移。

?哨兵模式的組成:

哨兵節點:?哨兵系統由一個或多個哨兵節點組成,哨兵節點是特殊的redis節點,不存儲數據。

數據節點:?主節點和從節點都是數據節點。

5.1? 哨兵模式的作用?

  • 監控:?哨兵會不斷地檢查主節點和從節點是否運作正常。
  • 自動故障轉移:?當主節點不能正常工作時,哨兵會開始自動故障轉移操,它會將失效主節點的其中一個從節點升級為新的主節點,并讓其它從節點改為復制新的主節點。
  • 通知(提醒):?哨兵可以將故障轉移的結果發送給客戶端。

此外:哨兵節點也可以是單獨獨立在其他的主機上,并不需要一定安裝redis主從復制的節點服務器上 、

5.2故障轉移機制

1、由哨兵節點定期監控發現主節點是否出現了故障

每個哨兵節點每隔1秒會問主節點、從節點及其它哨兵節點發送一次ping命令做一次心檢測。如果主節點在一定時間范圍內不回復或者是回復一個錯誤消息,那么這個哨兵就會認為這個主節點主觀下線了(單方面的)。當超過半數哨兵節點認為該主節點主觀下線了,這樣就客觀下線了。

2、當主節點出現故障,此時哨兵節點會通過Raft算法(選舉算法)實現選舉機制共同選舉出一個哨兵節點為leader,來負責處理主節點的故障轉移和通知。所以整個運行哨兵的集群的數量不得少于3個節點。

3、由leader哨兵節點執行故障轉移,過程如下:

  • 將某一個從節點升級為新的主節點,讓其它從節點指向新的主節點;
  • 若原主節點恢復也變成從節點,并指向新的主節點;
  • 通知客戶端主節點已經更換。

需要特別注意的是,客觀下線是主節點才有的概念;如果從節點和哨兵節點發生故障,被哨兵主觀下線后,不會再有后續的客觀下線和故障轉移操作

?5.3哨兵模式中主節點的選拔?

1.過濾掉不健康的(己下線的),沒有回復哨兵ping響應的從節點。

2.選擇配置文件中從節點優先級配置最高的。(replica-priority,默認值為100)

3.選擇復制偏移量最大,也就是復制最完整的從節點。

哨兵的啟動依賴于主從模式,所以須把主從模式安裝好的情況下再去做哨兵模式。

六、redis哨兵模式的部署(哨兵節點可以單獨配置或者放在數據節點一起配置)

主從 redis的版本號 IP地址 哨兵點
master redis-5.0.7 192.168.195.100 Sentinel 1
slave1 redis-5.0.7 192.168.195.200 Sentinel 2
slave2 redis-5.0.7 192.168.195.101 Sentinel 3

實驗具體操作步驟?

?在redis主從復制的基礎上進行哨兵模式的部署

步驟一:修改哨兵節點的配置文件

哨兵的的配置文件是redis軟件中自帶的配置?

vim /opt/redis-5.0.7/sentinel.conf
......
protected-mode no ? ? ? ? ? ? ? ?#17行,取消注釋,關閉保護模式
port 26379 ? ? ? ? ? ? ? ? ? ? ? #21行,Redis哨兵默認的監聽端口
daemonize yes ? ? ? ? ? ? ? ? ? ?#26行,指定sentinel為后臺啟動
logfile "/var/log/sentinel.log" ?#36行,指定日志文件存放路徑
dir "/var/lib/redis/6379" ? ? ? ?#65行,指定數據庫存放路徑
sentinel monitor mymaster 192.168.195.100?6379 2 ?#84行,修改
#指定該哨兵節點監控192.168.195.100:6379這個主節點,該主節點的名稱是mymaster。
#最后的2的含義與主節點的故障判定有關:至少需要2個哨兵節點同意,才能判定主節點故障并進行故障轉移
?
sentinel down-after-milliseconds mymaster 3000 ?#113行,判定服務器down掉的時間周期,默認30000毫秒(30秒)
sentinel failover-timeout mymaster 180000 ?#146行,同一個sentinel對同一個master兩次failover之間的間隔時間(180秒)
?
#傳給兩外2個哨兵節點
scp /opt/redis-5.0.7/sentinel.conf ?192.168.195.200:/opt/redis-5.0.7/
scp /opt/redis-5.0.7/sentinel.conf ?192.168.195.100:/opt/redis-5.0.7/

步驟二:啟動 哨兵模式,查看其監控狀態

#啟動三臺哨兵
cd /opt/redis-5.0.7/
redis-sentinel sentinel.conf &
?
#在哨兵節點查看監控狀態
[root@localhost ~]# redis-cli -p 26379 info Sentinel

實驗測試?

?故障模擬

#在Master 上查看redis-server進程號:
[root@localhost ~]# ps -ef | grep redis
?
#殺死 Master 節點上redis-server的進程號
[root@localhost ~]# kill -9 pid號 ? ? ?#Master節點上redis-server的進程號
[root@localhost ~]# netstat -natp | grep redis

實驗結果

?[root@localhost redis-5.0.7]# tail -f /var/log/sentinel.log
?
?
#新master進行鍵值對的創建
[root@localhost redis-5.0.7]# redis-cli?
127.0.0.1:6379> set newname lisi
OK
127.0.0.1:6379> get newname
"lisi"
127.0.0.1:6379>?

?七 Redis集群模式

集群,即Redis Cluster,是Redis3.0開始引入的分布式存儲方案。

集群由多個節點(Node)組成,Redis的數據分布在這些節點中。集群中的節點分為主節點和從節點:只有主節點負責讀寫請求和集群信息的維護;從節點只進行主節點數據和狀態信息的復制。

7.1集群的作用

(1)數據分區:?數據分區(或稱數據分片)是集群最核心的功能。

  • 集群將數據分散到多個節點,一方面突破了Redis單機內存大小的限制,存儲容量大大增加;另一方面每個主節點都可以對外提供讀服務和寫服務,大大提高了集群的響應能力。
  • Redis單機內存大小受限問題,在介紹持久化和主從復制時都有提及;例如,如果單機內存太大,bgsave和bgrewriteaof的fork操作可能導致主進程阻塞,主從環境下主機切換時可能導致從節點長時間無法提供服務,全量復制階段主節點的復制緩沖區可能溢出。

(2)高可用:?集群支持主從復制和主節點的自動故障轉移(與哨兵類似);當任一節點發生故障時,集群仍然可以對外提供服務。

?通過集群,Redis解決了寫操作無法負載均衡,以及存儲能力受到單機限制的問題,實現了較為完善的高可用方案。

7.2Redis集群的數據分片

Redis集群引入了哈希槽的概念。

Redis集群有16384個哈希槽(編號0-16383)。

集群的每個節點負責一部分哈希槽。

每個Key通過CRC16校驗后對16384取余來決定放置哪個哈希槽,通過這個值,去找到對應的插槽所對應的節點,然后直接自動跳轉到這個對應的節點上進行存取操作。

以3個節點組成的集群為例:

  • 節點A包含0到5460號哈希槽
  • 節點B包含5461到10922號哈希槽
  • 節點c包含10923到16383號哈希? ?槽

redis集群的部署

真實生產環境中,redis的cluster集群至少需要六臺服務器才能實現 ,如果因為電腦性能問題

可以嘗試redis多實例部署

實驗組件的部署?

安裝包:redis-5.0.7.tar.gz

192.168.195.100? ?我們就用一臺機器來搭建

cd /etc/redis/
mkdir -p redis-cluster/redis600{1..6} ? #創建redis集群的工作目錄、和每個節點的工作目錄
ls -R redis-cluster/

到軟件包目錄,把redis配置文件分別復制到我們第二步所創建的每個節點目錄中。也要把/opt/redis-5.0.7/src下的客戶端工具redis-cli和服務端命令redis-server復制到每個節點的目錄中

cd /opt/redis-5.0.7/src/
ls
cd /opt/redis-5.0.7/
for i in {1..6}; do cp /opt/redis-5.0.7/redis.conf /etc/redis/redis-cluster/redis600$i; cp /opt/redis-5.0.7/src/redis-server /opt/redis-5.0.7/src/redis-cli /etc/redis/redis-cluster/redis600$i; done ? ? ?
#使用for循環復制可以節省很多時間
cd /etc/redis/redis-cluster/
ls -R
?

修改每個節點目錄中的redis配置文件

cd redis6001
vim redis.conf
?
#bind 127.0.0.1 ? ? ##第69行;注釋掉監聽地址,表示監聽任意地址(也可設置為0.0.0.0)
protected-mode no ? ?#修改第88行,關閉保護模式,設置為no
port 6001 ? ? ? ? ? #修改第92行,修改監聽端口為6001
daemonize yes ? ? ? #修改第136行,開啟后臺運行
appendonly yes ? ? ?#修改第699行,開啟AOF持久化
?
?
#集群模式配置
cluster-enabled yes ? ?#第832行取消注釋,開啟集群模式
cluster-config-file nodes-6001.conf ? #第840行,每個集群配置文件,取消注釋、修改對應的端口(每個節點都要設置對應的)
cluster-node-timeout 15000 ? #第846行,集群節點之間通信的超時時間;取消注釋

啟動redis服務,一定要先進入每個節點目錄中去使用redis-server命令啟動


cd ../redis6001
ls
for i in {1..6}; do cd /etc/redis/redis-cluster/redis600$i; ./redis-server redis.conf; done
ps -elf |grep redis
redis-cli --cluster create 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:6004 127.0.0.1:6005 127.0.0.1:6006 --cluster-replicas 1 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? #把節點加入到集群當中
--cluster-replicas ? ?指定每個主節點有多少個從節點做主從復制
?
?
redis-cli -p 6001 ? ?#登錄redis數據庫
cluster slots ? ? ? ?#查看主從對應關系

?

驗證,鍵的插入

redis-cli -p 6001 -c ? ?
-c ?實現節點間的跳轉,如果不加會報錯
set name hj

??登錄到6004節點

redis-cli -p 6004 -c
keys *
get name

Redis集群拓展:

數據量過多如何處理?

當數據量過多的情況下,一種簡單的方式是升級Redis實例的資源配置,包括增加內存容量、磁盤容量、更好配置的CPU等,但這種情況下Redis使用RDB進行持久化的時候響應會變慢,Redis通過fork子進程來完成數據持久化,但fork在執行時會阻塞主線程,數據量越大,fork的阻塞時間就越長,從而導致Redis響應變慢。

Redis的切片集群可以解決這個問題,也就是啟動多個Redis實例來組成一個集群,再按照一定的規則把數據劃分為多份,每一份用一個實例來保存,這樣客戶端只需要訪問對應的實例就可以獲取數據。在這種情況下fork子進程一般不會給主線程帶來較長時間的阻塞,如下圖:

切片集群架構圖
將20GB的數據分為4分,每份包含5GB數據,客戶端只需要找到對應的實例就可以獲取數據,從而減少主線程阻塞的時間。

當數據量過多的時候,可以通過升級Redis實例的資源配置或者通過切片集群的方式。前者實現起來簡單粗暴,但這數據量增加的時候,需要的內存也在不斷增加,主線程fork子進程就有可能會阻塞,而且該方案受到硬件和成本的限制。相比之下第二種方案是一種擴展性更好的方案,如果想保存更多的數據,僅需要增加Redis實例的個數,不用擔心單個實例的硬件和成本限制。在面向百萬、千萬級別的用戶規模時,橫向擴展的 Redis 切片集群會是一個非常好的選擇。

選擇切片集群也是需要解決一些問題的:

  • 數據切片后,在多個實例之間怎么分布?
  • 客戶端怎么確定想要訪問的實例是哪一個?

Redis采用了Redis Cluster的方案來實現切片集群,具體的Redis Cluster采用了哈希槽(Hash Slot)來處理數據和實例之間的映射關系。在Redis Cluster中,一個切片集群共有16384個哈希槽(為什么Hash Slot的個數是16384),這些哈希槽類似于數據的分區,每個鍵值對都會根據自己的key被影射到一個哈希槽中,映射步驟如下:

  • 根據鍵值對key,按照CRC16算法計算一個16bit的值。
  • 用計算的值對16384取模,得到0~16383范圍內的模數,每個模數對應一個哈希槽。

這時候可以得到一個key對應的哈希槽了,哈希槽又是如何找到對應的實例的呢?

在部署Redis Cluster的時候,可以通過cluster create命令創建集群,此時Redis會自動把這些槽分布在集群實例上,例如一共有N個實例,那么每個實例包含的槽個數就為16384/N。當然可能存在Redis實例中內存大小配置不一的問題,內存大的實例具有更大的容量。這種情況下可以通過cluster addslots命令手動分配哈希槽。

redis-cli -h 33.33.33.3 –p 6379 cluster addslots 0,1redis-cli -h 33.33.33.4 –p 6379 cluster addslots 2,3redis-cli -h 33.33.33.5 –p 6379 cluster addslots 4
復制代碼
復制代碼

要注意的是,如果采用cluster addslots的方式手動分配哈希槽,需要將16384個槽全部分配完,否則Redis集群無法正常工作。現在通過哈希槽,切片集群就實現了數據到哈希槽、哈希槽到實例的對應關系,那么客戶端如何確定需要訪問的實例是哪一個呢?

(二)客戶端定位集群中的數據

客戶端請求的key可以通過CRC16算法計算得到,但客戶端還需要知道哈希槽分布在哪個實例上。在最開始客戶端和集群實例建立連接后,實例就會把哈希槽的分配信息發給客戶端,實例之間會把自己的哈希槽信息發給和它相連的實例,完成哈希槽的擴散。這樣客戶端訪問任何一個實例的時候,都能獲取所有的哈希槽信息。當客戶端收到哈希槽的信息后會把哈希槽對應的信息緩存在本地,當客戶端發送請求的時候,會先找到key對應的哈希槽,然后就可以給對應的實例發送請求了。

但是,哈希槽和實例的對應關系不是一成不變的,可能會存在新增或者刪除的情況,這時候就需要重新分配哈希槽;也可能為了負載均衡,Redis需要把所有的實例重新分布。

雖然實例之間可以互相傳遞消息以獲取最新的哈希槽分配信息,但是客戶端無法感知這個變化,就會導致客戶端訪問的實例可能不是自己所需要的了。

Redis Cluster提供了重定向的機制,當客戶端給實例發送數據讀寫操作的時候,如果這個實例上沒有找到對應的數據,此時這個實例就會給客戶端返回MOVED命令的相應結果,這個結果中包含了新實例的訪問地址,此時客戶端需要再給新實例發送操作命令以進行讀寫操作,MOVED命令如下:

GET hello:key(error) MOVED  33.33.33.33:6379
復制代碼
復制代碼

返回的信息代表客戶端請求的key所在的哈希槽為3333,實際是在33.33.33.33這個實例上,此時客戶端只需要向33.33.33.33這個實例發送請求就可以了。

此時也存在一個小問題,哈希槽中對應的數據過多,導致還沒有遷移到其他實例,此時客戶端就發起了請求,在這種情況下,客戶端就對實例發起了請求,如果數據還在對應的實例中,會給客戶端返回數據;如果請求的數據已經被轉移到其他實例上,客戶端就會收到實例返回的ASK命令,該命令表示:哈希槽中數據還在前一種、ASK命令把客戶端需要訪問的新實例返回了。此時客戶端需要給新實例發送ASKING命令以進行請求操作。

值得注意的是ASK信息和MOVED信息不一樣,ASK信息并不會更新客戶端本地的緩存的哈希槽分配信息,也就是說如果客戶端再次訪問該哈希槽還是會請求之前的實例,直到數據遷移完成.


                

原文鏈接:https://blog.csdn.net/weixin_48271370/article/details/127854771

欄目分類
最近更新