一、Redis-Sentinel(哨兵)
1、介紹
Redis-Sentinel是redis官方推薦的高可用性解決方案,
當用redis作master-slave的高可用時,如果master本身宕機,redis本身或者客戶端都沒有實現主從切換的功能。
而redis-sentinel就是一個獨立運行的進程,用於監控多個master-slave集群,
自動發現master宕機,進行自動切換slave > master。
sentinel主要功能如下:
1. 不時的監控redis是否良好運行,如果節點不可達就會對節點進行下線標識
2. 如果被標識的是主節點,sentinel就會和其他的sentinel節點“協商”,如果其他節點也認為主節點不可達,
就會選舉一個sentinel節點來完成自動故障轉移
3. 在master-slave進行切換后,master_redis.conf、slave_redis.conf和sentinel.conf的內容都會發生改變,
即master_redis.conf中會多一行slaveof的配置,sentinel.conf的監控目標會隨之調換
2、工作原理
每個Sentinel以每秒鍾一次的頻率向它所知的Master,Slave以及其他 Sentinel 實例發送一個 PING 命令 如果一個實例(instance)距離最后一次有效回復 PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個實例會被 Sentinel 標記為主觀下線。 如果一個Master被標記為主觀下線,則正在監視這個Master的所有 Sentinel 要以每秒一次的頻率確認Master的確進入了主觀下線狀態。 當有足夠數量的 Sentinel(大於等於配置文件指定的值)在指定的時間范圍內確認Master的確進入了主觀下線狀態, 則Master會被標記為客觀下線 在一般情況下, 每個 Sentinel 會以每 10 秒一次的頻率向它已知的所有Master,Slave發送 INFO 命令 當Master被 Sentinel 標記為客觀下線時,Sentinel 向下線的 Master 的所有 Slave 發送 INFO 命令的頻率會從 10 秒一次改為每秒一次 若沒有足夠數量的 Sentinel 同意 Master 已經下線, Master 的客觀下線狀態就會被移除。 若 Master 重新向 Sentinel 的 PING 命令返回有效回復, Master 的主觀下線狀態就會被移除。 主觀下線和客觀下線 主觀下線:Subjectively Down,簡稱 SDOWN,指的是當前 Sentinel 實例對某個redis服務器做出的下線判斷。 客觀下線:Objectively Down, 簡稱 ODOWN,指的是多個 Sentinel 實例在對Master Server做出 SDOWN 判斷,並且通過 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下線判斷,然后開啟failover. SDOWN適合於Master和Slave,只要一個 Sentinel 發現Master進入了ODOWN, 這個 Sentinel 就可能會被其他 Sentinel 推選出, 並對下線的主服務器執行自動故障遷移操作。 ODOWN只適用於Master,對於Slave的 Redis 實例,Sentinel 在將它們判斷為下線前不需要進行協商, 所以Slave的 Sentinel 永遠不會達到ODOWN。
3、master宕機處理
如果master宕機,我們應該先選一個slave出來,讓他成為新的master,其他redis都修改成這個新的master的slave,
但是redis本身或者客戶端都沒有實現主從切換的功能,當然,人為地修改配置文件,實現上圖的功能也是可以的,
但是如果是在深夜,所有人都睡覺了呢,誰來修改配置信息?
這個時候就可以使用redis的Sentinel功能了,它就是實現了,當發現master宕機,自動幫我們去修改其他redis配置文件,
選舉出一個新master。
4、Sentinel功能實現圖
5、redis一些查看命令
redis-cli info # 查看redis數據庫信息 redis-cli info replication # 查看redis的復制授權信息(主從復制) redis-cli info sentinel # 查看redis的哨兵信息
6、Redis主從配置
1.准備三個redis實例,一主兩從 # redis-6379.conf配置 port 6379 daemonize yes logfile "6379.log" dbfilename "dump-6379.rdb" dir "/var/redis/data/" # redis-6380.conf配置 port 6380 daemonize yes logfile "6380.log" dbfilename "dump-6380.rdb" dir "/var/redis/data/" slaveof 127.0.0.1 6379 # redis-6381.conf配置 port 6381 daemonize yes logfile "6381.log" dbfilename "dump-6381.rdb" dir "/var/redis/data/" slaveof 127.0.0.1 6379 2. 准備好了三個數據庫實例,啟動三個數據庫實例 # 啟動前記得先去創建redis數據存放的文件夾 mkdir -p /var/redis/data/ # 啟動實例 redis-server redis-6379.conf redis-server redis-6380.conf redis-server redis-6381.conf # 查看redis服務是否已經啟動 ps -ef | grep redis 3. 確定主從關系 redis-cli -p 6379 info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6380,state=online,offset=336,lag=0 slave1:ip=127.0.0.1,port=6381,state=online,offset=336,lag=1 redis-cli -p 6380 info replication # Replication role:slave master_host:127.0.0.1 master_port:6379
7、Redis Sentinel安裝配置
1. Sentinel配置解析 port 26379 // Sentinel的端口 dir /var/redis/data/ // Sentinel日志文件存放位置 logfile "26379.log" // Sentinel日志文件名字 // 當前Sentinel節點監控 127.0.0.1:6379 這個主節點 // 2代表判斷主節點失敗至少需要2個Sentinel節點節點同意 // mymaster是主節點的別名 sentinel monitor mymaster 127.0.0.1 6379 2 // 每個Sentinel節點都要定期PING命令來判斷Redis數據節點和其余Sentinel節點是否可達 // 如果超過30000毫秒30s且沒有回復,則判定不可達 sentinel down-after-milliseconds mymaster 30000 // 當Sentinel節點集合對主節點故障判定達成一致時,Sentinel領導者節點會做故障轉移操作,選出新的主節點, // 原來的從節點會向新的主節點發起復制操作,限制每次向新的主節點發起復制操作的從節點個數為1 sentinel parallel-syncs mymaster 1 //故障轉移超時時間為180000毫秒 sentinel failover-timeout mymaster 180000 // 后台執行 daemonize yes 2. 准備三個哨兵,開始監控主從架構 # 哨兵配置文件redis-26379.conf port 26379 dir /var/redis/data/ logfile "26379.log" sentinel monitor zbjmaster 127.0.0.1 6379 2 sentinel down-after-milliseconds zbjmaster 30000 sentinel parallel-syncs zbjmaster 1 sentinel failover-timeout zbjmaster 180000 daemonize yes # 哨兵配置文件redis-26380.conf port 26380 dir /var/redis/data/ logfile "26380.log" sentinel monitor zbjmaster 127.0.0.1 6379 2 sentinel down-after-milliseconds zbjmaster 30000 sentinel parallel-syncs zbjmaster 1 sentinel failover-timeout zbjmaster 180000 daemonize yes # 哨兵配置文件redis-26381.conf port 26381 dir /var/redis/data/ logfile "26381.log" sentinel monitor zbjmaster 127.0.0.1 6379 2 sentinel down-after-milliseconds zbjmaster 30000 sentinel parallel-syncs zbjmaster 1 sentinel failover-timeout zbjmaster 180000 daemonize yes 3. 啟動三個哨兵實例 redis-sentinel redis-26379.conf redis-sentinel redis-26380.conf redis-sentinel redis-26381.conf 注意!!如果發現實驗不成功,需刪掉所有的哨兵配置文件,從新來過 注意!!如果發現實驗不成功,需刪掉所有的哨兵配置文件,從新來過 注意!!如果發現實驗不成功,需刪掉所有的哨兵配置文件,從新來過 # 檢查哨兵狀態是否正常 # 只有發現如下信息,即為正常 redis-cli -p 26379 info sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 # 最重要的一句 master0:name=zbjmaster,status=ok,address=127.0.0.1:6380,slaves=2,sentinels=3 4. 測試哨兵的自動主從切換 1,干掉6379的redis數據庫 kill -9 6379的PID 2,查看6380和6381的身份信息,是否自動的進行主從切換 我們設置的是30s后master沒有響應,哨兵自動進行主從切換,因此30s后查看主從信息 redis-cli -p 6380 info replication redis-cli -p 6381 info replication 3,手動啟動6379掛掉的數據庫,查看是否會被哨兵,添加進信息的主從集群 redis-server redis-6379.conf redis-cli -p 6379 info replication
二、redis分區和集群
1、什么是分區和集群
1. 分區
分區是分割數據到多個Redis實例的處理過程,因此每個實例只保存key的一個子集。
分區可以讓Redis管理更大的內存,Redis將可以使用所有機器的內存。如果沒有分區,你最多只能使用一台機器的內存。
分區使Redis的計算能力通過簡單地增加計算機得到成倍提升,Redis的網絡帶寬也會隨着計算機和網卡的增加而成倍增長。
2. 集群
redis集群就是分區的一種的實現
2、為什么要用分區
1. 並發問題
官方聲稱 redis 每秒可以執行10萬條命令
但是假如業務需要每秒100萬的命令執行呢(例如新浪微博某某明星出軌、官宣之類的)
2. 數據量
當數據量太大的時候,一台服務器內存正常是16~256G,假如你的業務需要500G內存,怎么辦?
3. 解決方案
方案一:
配置一台超級牛逼的服務器,擁有超大內存和超強的cpu,
但是這么做的成本是非常高的,而且,萬一這台機器宕掉了,那你的服務還不是全掛了。
方案二:
考慮分布式,加機器,把數據分到不同的位置,分攤集中式的壓力,一堆機器做一件事。
3、分區的數據分布理論
redis是一個非關系型數據庫,它的存儲是key-value形式的,
redis實例集群主要思想是將redis數據的key進行散列,通過hash函數特定的key會映射到指定的redis節點上
分布式數據庫首要解決把整個數據集按照分區規則映射到多個節點的問題,即把數據集划分到多個節點上,每個節點負責整個數據的一個子集。
常見的分區規則有哈希分區和順序分區。
4、順序分區
假設我有三個節點,100個redis的數據,按照平均值(幾乎是平均的),順序分區的規則就是:
把1-33個數據 放在 node1
把34-66個數據 放在node2
把67-100個數據 放在node3
5、哈希分區
1. 哈希分區的規則
1, 節點取余分區
2, 一致性哈希分區
3, 虛擬槽分區(redis-cluster采用的方式)
2. 節點取余
例如按照節點取余的方式,分三個節點
1~100的數據對3取余,可以分為三類
余數為0
余數為1
余數為2
把余數為0的數據存到同一個節點
把余數為1的數據存到同一個節點
把余數為2的數據存到同一個節點
那么同樣的分4個節點就是hash(key)%4,余數相同的存到同一個節點
節點取余的優點是簡單,客戶端分片直接是哈希+取余
3. 一致性哈希
客戶端進行分片,哈希+順時針取余
4. 虛擬槽分區
本文研究哈希分區之虛擬槽分區,因此下面單獨來聊一聊
三、哈希分區之虛擬槽分區
1、介紹
Redis Cluster采用的就是虛擬槽分區
虛擬槽分區巧妙地使用了哈希空間,使用分散度良好的哈希函數把所有的數據映射到一個固定范圍內的整數集合,
這些整數就定義為槽(slot)。
Redis Cluster槽的范圍是0 ~ 16383,即一共16384個槽。
槽是集群內數據管理和遷移的基本單位。采用大范圍的槽的主要目的是為了方便數據的拆分和集群的擴展,
每個節點(redis實例)負責一定數量的槽。
2、虛擬槽圖解
3、搭建redis cluster
redis支持多實例的功能,我們在單機演示集群搭建,需要6個實例,三個是主節點,三個是從節點,數量為6個節點才能保證高可用的集群。
1.准備6個節點,用於存儲數據,分配槽位,每個節點的配置,如下,僅僅是端口的區別 # redis-7000.conf配置 port 7000 daemonize yes dir "/opt/redis/data" logfile "7000.log" dbfilename "dump-7000.rdb" cluster-enabled yes cluster-config-file nodes-7000.conf 其余5個配置跟上面一模一樣,僅僅是端口的區別 # redis-7001.conf配置 # redis-7002.conf配置 # redis-7003.conf配置 # redis-7004.conf配置 # redis-7005.conf配置 注意:要創建存放日志的文件夾 mkdir -p /opt/redis/data 2.啟動6個數據庫實例 redis-server redis-7000.conf redis-server redis-7001.conf redis-server redis-7002.conf redis-server redis-7003.conf redis-server redis-7004.conf redis-server redis-7005.conf 3.開始分配redis集群狀態,以及槽位分配 Redis Cluster本身提供了自動將數據分散到Redis Cluster不同節點的能力, 但是槽位的分配就比較麻煩了,當然了,如果你是大神,你完全可以自定義槽位的分配, 一些大神已經寫好了槽位分配的工具或腳本了,例如豆瓣公司開源的codis工具,還有ruby語言的作者,寫的redsi.rb, 因此我們可以使用一些工具幫我們進行redis cluster的搭建 4.通過ruby腳本,一鍵創建redis-cluster,進行槽位分配 5.准備ruby的編程環境 1,下載ruby的源碼包 wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz 2,解壓縮ruby遠嗎 tar -zxvf ruby-2.3.1.tar.gz 3,開始編譯安裝ruby 進入ruby源碼包 ./configure --prefix=/opt/ruby/ 4,開始編譯且編譯安裝 make && make install 5,配置ruby的環境變量 vim /etc/profile 寫入如下配置 PATH=你原本的PATH:/opt/ruby/bin source /etc/profile 6.安裝ruby操作redis的模塊 1,下載ruby操作redis的模塊 wget http://rubygems.org/downloads/redis-3.3.0.gem 2,安裝 gem install -l redis-3.3.0.gem 3,搜索創建redis集群的命令 find /opt -name redis-trib.rb /opt/redis-4.0.10/src/redis-trib.rb 7.一鍵創建redis集群 /opt/redis-4.0.10/src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --replicas 進行身份授權 后面的1 代表,每個主節點,只有一個從節點 默認將 7000 7001 70002 設置為主庫 將7003 7004 7005 設置為從庫 8.檢查集群狀態 redis-cli -p 7000 cluster info 9.測試集群節點,看是否能正常寫入數據 redis-cli -c -p 7000 -p 指定數據庫端口 -c 指定開啟集群模式 set age 18 # 設置一個key會自動分配槽位,重定向到槽位所在的節點即代表成功 在任意一個節點都可以get age,會自動重定向到 age 所在的節點。 10.redis-cluster 會默認將不同的key,進行CRC16算法,進行分配到不同槽位 11.數據正常重定向,即redis集群ok