三千字介紹Redis主從+哨兵+集群


一、Redis持久化策略

1.RDB

每隔幾分鍾或者一段時間會將redis內存中的數據全量的寫入到一個文件中去。

優點:

  1. 因為他是每隔一段時間的全量備份,代表了每個時間段的數據。所以適合做冷備份。
  2. RDB對redis的讀寫影響非常小,因為redis主進程只需要fork一個子進程進行磁盤IO操作就行了。
  3. 相對於AOF來說,恢復較快,因為一個RDB就是數據文件,而AOF存的是指令日志。

缺點:

  1. 因為是一段時間才備份,所以容易丟數據。
  2. 如果一次寫入的文件大,會導致讀寫服務暫停幾毫秒,甚至幾秒。

2.AOF

會將每條寫入指令都寫入到linux os緩存中去,然后每秒鍾會將linux os中的指令作為日志追加到AOF的文件里面。

當redis內存大小達到一定的量,會通過LRU(最近最少使用)淘汰機制淘汰掉數據,然后再重寫一個新的AOF文件出來。這樣也保證了AOF文件不會無限制的增大。

優點:

  1. 不易丟數據
  2. AOF日志文件是以append-only的模式寫入,沒有磁盤尋址的開銷,寫入性能高,文件也不易破損
  3. AOF文件過大的時候,后台重寫操作,也不會影響客戶端。再rewrite的時候,會對指令壓縮,創建出一份需要恢復的最小日志出來,再創建新日志文件時,老的文件照常寫入,當新文件准備好了,再交換新老日志文件就行了
  4. 日志文件的命令是可讀的,可以作為誤刪的緊急恢復。停了服務,再把那條刪除指令刪除,再恢復就行了。

缺點:

  1. AOF日志文件占用的磁盤空間比較大
  2. 開啟AOF后,寫操作的QPS會下降
  3. 以前出過bug,恢復的數據和原來不一樣,健壯性沒有RDB高
  4. 恢復數據慢,且不適合做冷備(需要手動寫腳本)

3.混合持久化(Redis 4.0)

開啟混合持久化

aof-use-rdb-preamble yes

綜合來說:

我們可以采用兩種都用的的方案,RDB做冷備,為了保證數據不丟失,AOF做數據恢復的第一選擇。

如何配置持久化?

  1. 找到/usr/local/package/redis-4.0.9/redis.conf

  2. RDB的配置

 //每隔60秒,如果有10000個key發生改變就持久化一次
    save 60 10000
  1. AOF的配置
    # redis默認關閉AOF機制,可以將no改成yes實現AOF持久化
    appendonly no
    # AOF文件
    appendfilename "appendonly.aof"
    # AOF持久化同步頻率,always表示每個Redis寫命令都要同步fsync寫入到磁盤中,但是這種方式會嚴重降低redis的速度;everysec表示每秒執行一次同步fsync,顯示的將多個寫命令同步到磁盤中;no表示讓操作系統來決定應該何時進行同步fsync,Linux系統往往可能30秒才會執行一次
    # appendfsync always
    appendfsync everysec
    # appendfsync no
    
    # 在日志進行BGREWRITEAOF時,如果設置為yes表示新寫操作不進行同步fsync,只是暫存在緩沖區里,避免造成磁盤IO操作沖突,等重寫完成后在寫入。redis中默認為no  
    no-appendfsync-on-rewrite no   
    # 當前AOF文件大小是上次日志重寫時的AOF文件大小兩倍時,發生BGREWRITEAOF操作。  
    auto-aof-rewrite-percentage 100  
    #當前AOF文件執行BGREWRITEAOF命令的最小值,避免剛開始啟動Reids時由於文件尺寸較小導致頻繁的BGREWRITEAOF。  
    auto-aof-rewrite-min-size 64mb  
    # Redis再恢復時,忽略最后一條可能存在問題的指令(因為最后一條指令可能存在問題,比如寫一半時突然斷電了)
    aof-load-truncated yes
    #Redis4.0新增RDB-AOF混合持久化格式,在開啟了這個功能之后,AOF重寫產生的文件將同時包含RDB格式的內容和AOF格式的內容,其中RDB格式的內容用於記錄已有的數據,而AOF格式的內存則用於記錄最近發生了變化的數據,這樣Redis就可以同時兼有RDB持久化和AOF持久化的優點(既能夠快速地生成重寫文件,也能夠在出現問題時,快速地載入數據)。
    aof-use-rdb-preamble no
  1. AOF rewrite過程

    1. redis fork一個子進程
    2. 子進程基於當前內存中的數據開始寫入一個新的aof的文件
    3. 這時新的命令進來,會存在內存中,也會存在舊的aof文件中
    4. 當新的aof文件寫好了,這個過程中的新的命令也會追加到aof里來
    5. 然后用新日志文件替換掉舊的日志文件

注意:當使用shutdown命令關閉redis服務時,會自動備份一個快照

當RDB生成快照時,AOF不會rewrite。反之亦然。

redis如果遇到斷電或機器故障問題時怎么辦?

答:一般使用持久化加服務器文件(將文件備份到阿里雲)備份的方案

二、Redis淘汰策略

LRU:(least recently used)最近最少使用

  1. 標准的LRU算法:

使用HashMap+雙向鏈表

核心步驟:

  1. save操作時,在hashmap中找對應的key值,如果存在,更新他並移到隊頭,如果不存在,則構建新節點,並移到隊頭,如果隊列滿了,則移除隊尾的節點,並在hashmap中移除該key
  2. get操作時,在hashmap中找到對應的節點,將他移到隊頭

redis里面沒有使用雙向鏈表的實現方式,而是使用了一個pool池.

  1. Redis的LRU實現

常用策略:allkeys-lru

Redis使用的是近似LRU算法

  • 給每個 key 增加一個額外 24bit 長度的小字段, 存儲該 key 的最后一次訪問時間戳
  • 當空間滿時, 隨機采樣取出 5 個 key (數量可配置), 按時間戳淘汰掉最舊的 key
  • 循環第二步, 直到內存低於 maxmemory 值
  • 隨機采樣的范圍取決於配置的策略是 volatile 還是 allkeys

Redis 3.0 開始, 增加了淘汰池進一步提升了近似 LRU 的效果:

  • 上一次隨機采樣后未淘汰的 key, 會放入 淘汰池 留待下一次循環,
  • 下一次隨機采樣的key會先和淘汰池中的key合並后, 再計算淘汰最舊的key

三、Redis主從架構

1.主從特性

  1. 采用異步的方式復制到slave節點,不過redis2.8之后,每個slave節點會周期性的確認自己每次復制的數據量
  2. 一個master可以配置多個slave
  3. slave node也可以連接其他的slave node
  4. slave復制時不影響master的工作
  5. slave復制時也不會影響slave的查詢操作,他會用舊的數據提供服務。但是當復制完成,需要刪除舊數據,加載新數據集時,會暫停服務。
  6. slave主要用來做橫向擴容,做讀寫分離

2.主從復制步驟

  1. 當slave第一次連接時,master會生成一個全量RDB文件給他做恢復,並將這個過程中新的寫入命令緩存在內存中,等slave把RDB文件讀入之后發給他
  2. 當slave斷開一段時間后重連,master會將缺失的數據發給他
  3. 平時情況下,master收到一個指令,都會馬上復制給slave

3.斷點續傳
從redis2.8開始,就支持主從復制的斷點續傳
master中存了backlog,master和slave都會保存一個replica offset,還有一個master id。如果中途網絡斷了,slave會讓master從上次的replica offset開始繼續復制。

4.過期key處理
slave不會過期key,只會等master過期key之后或者根據,模LRU淘汰了key之后擬一個del命令發給slave

5.配置主從服務器

  1. 安裝redis
  2. cp utils/redis_init_script /etc/init.d/redis_6379
  3. redis自啟動 chkconfig redis_6379 on
  4. mkdir /etc/redis
  5. mkdir -p /var/redis/6379
  6. cp redis.conf /etc/redis/6379.conf
  7. 修改配置文件6379.conf
  • daemonize yes //讓redis以daemon進程運行
  • dir /var/redis/6379
  • slaveof CentOS01 6379
  • slave 服務器的配置文件上配 masterauth 123456
  • master服務器的配置文件上配
    requirepass 123456
  • 每個6379.conf里都要將bind 127.0.0.1改成bind 自己本機的ip
  1. 讓redis跟隨系統啟動自動啟動

在redis_6379腳本中,最上面,加入兩行注釋

#chkconfig:   2345 90 10  
#description:  Redis is a persistent key-value database

然后執行
chkconfig redis_6379 on
8. 壓測性能 ./redis-benchmark -c 50 -n 10000

復制原理圖:

注意:主從架構建議必須開啟master節點的持久化。

四、哨兵模式

1.概念介紹

介紹:

  1. 集群監控,監控master和slave是否正常
  2. 消息通知,如果某個redis實例故障了,負責發消息給管理員
  3. 故障轉移,如果master節點掛掉了,會自動轉移到slave上
  4. 配置中心,如果故障轉移發生了,通知client新的master地址

2.故障轉移

哨兵至少要3個實例

如圖:

如果只有2個哨兵會如何呢?

master宕機,s1和s2中只要有1個哨兵認為master宕機就可以進行切換,同時s1和s2中會選舉出一個哨兵來執行故障轉移

同時這個時候,需要majority,也就是大多數哨兵都是運行的,2個哨兵的majority就是2(2的majority=2,3的majority=2,5的majority=3,4的majority=2),2個哨兵都運行着,就可以允許執行故障轉移

但是如果整個M1和S1運行的機器宕機了,那么哨兵只有1個了,此時就沒有majority來允許執行故障轉移,雖然另外一台機器還有一個R1,但是故障轉移不會執行

3.解決異步復制和腦裂導致的數據丟失

min-slaves-to-write 1
min-slaves-max-lag 10
要求至少有1個slave,數據復制和同步的延遲不能超過10秒

4.sdown和odown轉換機制
sdown:主觀宕機,即一個哨兵覺得master宕機了
odown:客觀宕機,即quorum數量的哨兵覺得master宕機了

5.哨兵集群的自動發現機制

哨兵互相之間的發現,是通過redis的pub/sub系統實現的,每個哨兵都會往__sentinel__:hello這個channel里發送一個消息,這時候所有其他哨兵都可以消費到這個消息,並感知到其他的哨兵的存在

每隔兩秒鍾,每個哨兵都會往自己監控的某個master+slaves對應的__sentinel__:hello channel里發送一個消息,內容是自己的host、ip和runid還有對這個master的監控配置

每個哨兵也會去監聽自己監控的每個master+slaves對應的__sentinel__:hello channel,然后去感知到同樣在監聽這個master+slaves的其他哨兵的存在

每個哨兵還會跟其他哨兵交換對master的監控配置,互相進行監控配置的同步

6.選舉算法

如果一個master被認為odown了,而且majority哨兵都允許了主備切換,那么某個哨兵就會執行主備切換操作,此時首先要選舉一個slave來

會考慮slave的一些信息

(1)跟master斷開連接的時長
(2)slave優先級
(3)復制offset
(4)run id

7.部署哨兵

  1. 復制配置文件
    mkdir -p /var/sentinel/5000
    mkdir /etc/sentinel
    mkdir -p /var/log/sentinal/5000
    mv /usr/local/package/redis-4.0.9/sentinel.conf /etc/sentinel/5000.conf
  1. 修改配置文件
  port 5000
  bind  192.168.1.14
  sentinel monitor mymaster 192.168.1.12 6379 2
  dir /var/sentinel/5000
  sentinel parallel-syncs mymaster 1
  sentinel failover-timeout mymaster 60000
  sentinel down-after-milliseconds mymaster 30000
  sentinel auth-pass mymaster 123456
  daemonize yes
  logfile /var/log/sentinal/5000/sentinel.log

注意:sentinel monitor mymaster 192.168.1.12 6379 2 這行要放在使用mymaster的那些其他配置之前

  1. 啟動哨兵

./redis-sentinel /etc/sentinel/5000.conf

五、redis集群

1.概念介紹

  1. 自動對數據進行分片,每個master上存放一部分數據
  2. 提供內置的高可用支持,部分master不可用了,還是可以繼續工作的

2.部署選型
redis cluster VS replication + sentinel

當數據量少,主要承載的是高並發時,單機就足夠了。一個master多個slave,在搭建一個sentinel集群來保證高可用性

redis cluster主要還是用來做海量數據的緩存。

3.分布式Hash算法

當需要把數據分到不同的幾個機器存儲時,就需要一個算法了。

  1. 方法一:取模
    對數據的hash值取模,比如有3台集器,那么就用hash%3,得到的就是0-2的三個數字,就可以確定將數據存在哪一台上面了

缺點:如果有一台機器掛掉了,那么數據會對2取模,那么得到的機器號就錯亂了,導致大量數據不能從正確的機器上去取

  1. 方法二:一致性hash算法(圓環算法)

將3台機器放在一個圓環上,然后要緩存的數據經過計算也落在圓環的某一個點,然后順時針去環上找離他最近的那個機器。

優點:當一台機器掛掉,不影響其他的機器上存的數據

缺點:具有熱點問題,可能某一個機器會有大量數據,這就需要將每個機器都多設置幾個虛擬節點,均勻分布在圓環上。

  1. 方法三:redis cluster的hash slot算法

redis cluster有固定的16384個slot,對每個key計算CRC16值,然后對16384取模,獲取對應的slot,每個master都有部分的slot。這樣的話如果增加一個master,就將其他master上的slot分點給她就行了。

4.部署redis集群

  1. 創建目錄
  mkdir -p /etc/redis-cluster
  mkdir -p /var/log/redis
  mkdir /var/redis/7001
  mkdir /var/redis/7002
  1. 修改配置文件 7001.conf
  port 7001
  cluster-enabled yes
  cluster-config-file /etc/redis-cluster/node-7001.conf
  cluster-node-timeout 15000
  pidfile "/var/run/redis_7001.pid"
  dir "/var/redis/7001"
  logfile "/var/log/redis/7001.log"
  1. 修改配置文件
vi /usr/local/share/gems/gems/redis-3.2.1/lib/redis/client.rb

password=123456
  1. 執行
 echo never > /sys/kernel/mm/transparent_hugepage/enabled
  1. 啟動腳本
   cd /etc/init.d/
   cp redis_6379 redis_7001
修改redis_7001配置

  REDISPORT=7001
  1. 安裝ruby
   yum install -y ruby
    下載一個redis-3.2.1.gem,然后執行
    gem install redis
    
    cp /usr/local/package/redis-4.0.9/src/redis-trib.rb /usr/local/bin
    
    /usr/local/bin/redis-trib.rb create --replicas 1 192.168.1.12:7001 192.168.1.12:7002 192.168.1.13:7003 192.168.1.13:7004 192.168.1.14:7005 192.168.1.14:7006
  1. 檢查節點狀態
 ./redis-trib.rb check 192.168.1.12 7001


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM