1.redis特點
(1)基於內存 (2)可持久化數據 (3)具有豐富的數據結構類型,適應非關系型數據的存儲需求 (4)支持絕大多數主流開發語言,如C、C++、Java、Python、R、JavaScript等。 (5)支持集群模式,高效、穩定。
2.數據類型
(1)鍵值對形式。 (2)Redis的數據結構類型,指的就是Redis值的結構類型。
3. Redis作用
(1)本質是數據庫,能存儲數據。 Redis能靈活處理非關系型數據的讀、寫問題,是對MySQL等關系型數據庫的補充。 新浪微博就是使用Redis集群做數據庫 (2)緩存數據。 所謂緩存,就是將數據加載到內存中后直接使用,而不是每次都通過IO流從磁盤上讀取。好處:讀寫效率高。 而Redis則是將數據直接存儲在內存中,只有當內存空間不足時,將部分數據持久化到磁盤上。
4.下載安裝
# 官網下載 https://redis.io/download $ wget https://download.redis.io/releases/redis-5.0.10.tar.gz $ tar xzf redis-5.0.10.tar.gz $ cd redis-5.0.10 $ make $ make install
# make MALLOC=libc (有時候直接make有報錯)
# redis啟動命令,如果沒發現redis-server去redis/src/目錄查看
redis-server /usr/local/redis/redis.conf
關閉命令(如果有多個redis在同一台機器,需帶上端口和IP,如果設置了密碼也需要密碼關閉 -a 'password'):
redis-cli -h 127.0.0.1 -p 6379 shutdown

#!/bin/sh # # Simple Redis init.d script conceived to work on Linux systems # as it does use of the /proc filesystem. # chkconfig: 2345 90 10 ### BEGIN INIT INFO # Provides: redis_6379 # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Redis data structure server # Description: Redis data structure server. See https://redis.io ### END INIT INFO #redis服務器監聽的端口 REDISPORT=6379 #服務端所處位置 EXEC=/usr/local/bin/redis-server #客戶端位置 CLIEXEC=/usr/local/bin/redis-cli #redis的PID文件位置,根據實際情況修改 PIDFILE=/var/run/redis_${REDISPORT}.pid #redis的配置文件位置,需將${REDISPORT}修改為文件名 CONF="/usr/local/redis/${REDISPORT}.conf" case "$1" in start) if [ -f $PIDFILE ] then echo "$PIDFILE exists, process is already running or crashed" else echo "Starting Redis server..." $EXEC $CONF fi ;; stop) if [ ! -f $PIDFILE ] then echo "$PIDFILE does not exist, process is not running" else PID=$(cat $PIDFILE) echo "Stopping ..." $CLIEXEC -p $REDISPORT shutdown while [ -x /proc/${PID} ] do echo "Waiting for Redis to shutdown ..." sleep 1 done echo "Redis stopped" fi ;; *) echo "Please use start or stop as first argument" ;; esac
5.redis常用配置文件
bind:允許訪問該redis的主機 protected-mode:保護模式,默認開啟。若設置外部網絡連接redis服務,設置方式如下: 1、關閉protected-mode模式,此時外部網絡可以直接訪問 2、開啟protected-mode保護模式,需配置bind ip或者設置訪問密碼,或者bind ip和密碼都設置 requirepass:設置密碼 databases:Redis默認有16個數據庫,尋址角標從0開始。默認連接db0。客戶端使用select命令,切換數據庫 port :指定redis的服務端口,默認6379. daemonize:Redis默認關閉后台進程模式,改成yes,redis服務在后台啟動。 loglevel :日志等級 logfile:Redis日志輸出目錄,默認不輸出日志到文件。 dbfilename:指定數據持久化的文件名 dir :指定數據持久化的文件存放目錄,也是集群node.con文件存放目錄 cluster-enabled:是否啟用集群 cluster-config-file:集群文件
6. redis持久化
Redis持久化,就是將內存中的數據,永久保存到磁盤上。
Redis持久化有兩種方式:RDB(Redis DB)、AOF(AppendOnlyFile)
Redis 可以同時使用 AOF 持久化和 RDB 持久化。 在這種情況下, 當 Redis 重啟時, 它會優先使用 AOF 文件來還原數據集, 因為 AOF 文件保存的數據集通常比 RDB 文件所保存的數據集更完整。
6.1 RDB快照模式
# 在默認情況下,Redis 將數據庫快照保存在名字為dump.rdb的二進制文件中,可以在redis.conf配置文件中修改持久化信息。 save 900 1 表示在900秒內,至少更新了1條數據。Redis就將數據持久化到硬盤 save 300 10 表示在300內,至少更新了10條數據,Redis就會觸發將數據持久化到硬盤 save 60 10000 表示60秒內,至少更新了10000條數據,Redis就會觸發將數據持久化到硬盤
6.1.1 策略 1. 自動保存:BGSAVE 按照配置文件中的條件滿足就執行BGSAVE; 非阻塞,Redis服務正常接收處理客戶端請求; Redis會folk()一個新的子進程來創建RDB文件,子進程處理完后會向父進程發送一個信號,通知它處理完畢; 父進程用新的dump.rdb替代舊文件。 2.手動保存:SAVE 客戶端(redis-cli)發起SAVE命令; 阻塞Redis服務,無法響應客戶端請求; 創建新的dump.rdb替代舊文件。 6.1.2 優點 執行效率高; 恢復大數據集速度較AOF快。 6.1.3 缺點 會丟失最近寫入、修改的而未能持久化的數據; folk過程非常耗時,會造成毫秒級不能響應客戶端請求。
6.2 AOF模式(追加模式、文本重演)
AOF默認關閉,需要在配置文件中手動開啟。 記錄所有的寫操作命令,在服務啟動的時候使用這些命令就可以還原數據庫。 Append only file,采用追加的方式保存,默認文件appendonly.aof。
6.2.1 寫入機制 AOF機制,添加了一個內存緩沖區(buffer): 將內容寫入緩沖區 當緩沖區被填滿、或者用戶手動執行fsync、或者系統根據指定的寫入磁盤策略自動調用fdatasync命令,才將緩沖區里的內容真正寫入磁盤里 在緩沖區里的內容未寫入磁盤之前,可能會丟失 6.2.2 寫入磁盤的策略 appendfsync選項,這個選項的值可以是always、everysec或者no always:服務器每寫入一個命令,就調用一次fdatasync,將緩沖區里面的命令寫入到硬盤。這種模式下,服務器出現故障,也不會丟失任何已經成功執行的命令數據 everysec(默認):服務器每一秒重調用一次fdatasync,將緩沖區里面的命令寫入到硬盤。這種模式下,服務器出現故障,最多只丟失一秒鍾內的執行的命令數據 no:服務器不主動調用fdatasync,由操作系統決定何時將緩沖區里面的命令寫入到硬盤。這種模式下,服務器遭遇意外停機時,丟失命令的數量是不確定的,no 選項並不能給服務器性能帶來多大的提升,而且也會增加系統奔潰時數據丟失的數量。 運行速度:always的速度慢,everysec和no都很快
7.Redis主從復制
概念 主從復制模型中,有多個redis節點。 其中,有且僅有一個為主節點Master。從節點Slave可以有多個。 只要網絡連接正常,Master會一直將自己的數據更新同步給Slaves,保持主從同步。 特點 (1)主節點Master可讀、可寫. (2)從節點Slave只讀。(read-only) 因此,主從模型可以提高讀的能力,在一定程度上緩解了寫的能力。因為能寫仍然只有Master節點一個,可以將讀的操作全部移交到從節點上,變相提高了寫能力。
配置:
環境: 系統:centos 7.7 master:192.168.0.111:6380 slave:192.168.0.112:6380,6381
修改redis.conf共8處,即可實現一個主從Redis搭建. 還是很簡單的.現在我們正式開始搭建吧. 69行: bind 127.0.0.1 改為: bind 0.0.0.0 需要跨服務器訪問,如果是生產最好指定IP或添加防火牆. 88行: protected-mode yes 改為: protected-mode no 如果是yes保護模式,需要配置bind或者設置密碼,no的話則設置 92行: port 6379 改為: port 6381 訪問端口 136行:daemonize no 改為: daemonize yes 守護進程模式運行 158行: pidfile /var/run/redis.pid 改為: pidfile /var/run/redis_6381.pid 啟動使用的PID 263行: dir ./ 改為: dir /usr/local/redis-ms/6381/ 存儲日志與數據文件的目錄 287行: replicaof <masterip> <masterport> 改為:replicaof 192.168.21.22 6381 (從redis.conf配置才設置) 294行: # masterauth <master-password> 改為: masterauth o9bEuO6iDKrIhYkx slave節點設置master的密碼, 507行: #requirepass 123456 改為: requirepass o9bEuO6iDKrIhYkx 設置訪問時需要的密碼
master配置文件:
bind 192.168.0.111 protected-mode no port 6380 daemonize no # 先改為no,測試時可以看到打印的日志,正式環境改為yes pidfile /var/run/redis_6380.pid dir /usr/local/redis/master/ requirepass 123456 # 其余的參數可以自己去選擇性配置
slave配置:
cd /usr/local/redis mkdir slave/6380 -p mkdir slave/6381 -p cp redis.conf slave/6380/6380.conf cp redis.conf slave/6381/6381.conf # slave 1 配置 bind 192.168.0.112 protected-mode yes port 6380 pidfile /var/run/redis_6380.pid replicaof 192.168.0.111 6380 masterauth 123456 # slave2根據slave1只需要修改端口就行
啟動redis后登錄:
# master: 啟動后可以看到: Synchronization with replica 192.168.0.112:6380 succeeded Synchronization with replica 192.168.0.112:6381 succeeded redis-cli -p 6380 -a '123456' -h 192.168.0.111 192.168.0.111:6380> set cx cxiong OK
192.168.0.111:6380> info Replication #此命令也可以看到詳細信息
slave0:ip=192.168.0.112,port=6380,state=online,offset=683,lag=1
# slave1 和slave2 redis-cli -p 6380 -h 192.168.0.112 192.168.0.112:6380> get cx "cxiong" # 寫操作執行失敗提示 (error) READONLY You can't write against a read only replica.

bind 192.168.0.112 protected-mode yes port 6380 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize no supervised no pidfile /var/run/redis_6380.pid loglevel notice logfile "" databases 16 always-show-logo yes save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir /usr/local/redis/slave/6380/ replicaof 192.168.0.111 6380 masterauth 123456 replica-serve-stale-data yes replica-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-ping-replica-period 10 repl-timeout 10 repl-disable-tcp-nodelay no replica-priority 100 lazyfree-lazy-eviction no lazyfree-lazy-expire no lazyfree-lazy-server-del no replica-lazy-flush no appendonly no appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes aof-use-rdb-preamble yes lua-time-limit 5000 slowlog-log-slower-than 10000 slowlog-max-len 128 latency-monitor-threshold 0 notify-keyspace-events "" hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 stream-node-max-bytes 4096 stream-node-max-entries 100 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit replica 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 dynamic-hz yes aof-rewrite-incremental-fsync yes rdb-save-incremental-fsync yes
8. Redis集群--Sentinel哨兵模式
1.主從模式缺陷 當主節點宕機了,整個集群就沒有可寫的節點了。 問:由於從節點上備份了主節點的所有數據,那在主節點宕機的情況下,如果能夠將從節點變成一個主節點,是不是就可以解決這個問題了呢? 答:是的,這個就是Sentinel哨兵的作用。 2.哨兵的任務 Redis 的 Sentinel 系統用於管理多個 Redis 服務器(instance), 該系統執行以下三個任務: (1) 監控(Monitoring): Sentinel 會不斷地檢查你的主服務器和從服務器是否運作正常。 (2) 提醒(Notification): 當被監控的某個 Redis 服務器出現問題時, Sentinel 可以通過 API 向管理員或者其他應用程序發送通知。 (3) 自動故障遷移(Automatic failover): 當一個主服務器不能正常工作時, Sentinel 會開始一次自動故障遷移操作, 它會進行選舉,將其中一個從服務器升級為新的主服務器, 並讓失效主服務器的其他從服務器改為復制新的主服務器; 當客戶端試圖連接失效的主服務器時, 集群也會向客戶端返回新主服務器的地址, 使得集群可以使用新主服務器代替失效服務器。 3.監控(Monitoring) (1)Sentinel可以監控任意多個Master和該Master下的Slaves。(即多個主從模式) (2)同一個哨兵下的、不同主從模型,彼此之間相互獨立。 (3)Sentinel會不斷檢查Master和Slaves是否正常。 4.自動故障切換(Automatic failover) 監控同一個Master的Sentinel會自動連接,組成一個分布式的Sentinel網絡,互相通信並交換彼此關於被監視服務器的信息。 疑問:為什么要使用sentinel網絡呢? 答:當只有一個sentinel的時候,如果這個sentinel掛掉了,那么就無法實現自動故障切換了。 在sentinel網絡中,只要還有一個sentinel活着,就可以實現故障切換。 5.故障切換的過程 (1)投票(半數原則) 當任何一個Sentinel發現被監控的Master下線時,會通知其它的Sentinel開會,投票確定該Master是否下線(半數以上,所以sentinel通常配奇數個)。 (2)選舉 當Sentinel確定Master下線后,會在所有的Slaves中,選舉一個新的節點,升級成Master節點。 其它Slaves節點,轉為該節點的從節點。 (3)原Master重新上線 當原Master節點重新上線后,自動轉為當前Master節點的從節點。
8.1哨兵模式部署
使用哨兵模式需要先搭建一個主2從
# 查看主從 192.168.0.111:6380> info replication # Replication role:master connected_slaves:2 slave0:ip=192.168.0.112,port=6380,state=online,offset=578465,lag=0 slave1:ip=192.168.0.110,port=6380,state=online,offset=578465,lag=1 master_replid:550a9019ed53d63e31a678211425fab96da6ddcb master_replid2:ef254865cc0a493e33bbc0f88694ac93263e7b10 master_repl_offset:578465 second_repl_offset:511899 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:466560 repl_backlog_histlen:111906
sentinel monitor <master-name> <ip> <redis-port> <quorum> 告訴sentinel去監聽地址為ip:port的一個master,這里的master-name可以自定義,quorum是一個數字,指明當有多少個sentinel認為一個master失效時,master才算真正失效 sentinel auth-pass <master-name> <password> 設置連接master和slave時的密碼,注意的是sentinel不能分別為master和slave設置不同的密碼,因此master和slave的密碼應該設置相同。 sentinel down-after-milliseconds <master-name> <milliseconds> 這個配置項指定了需要多少失效時間,一個master才會被這個sentinel主觀地認為是不可用的。 單位是毫秒,默認為30秒 sentinel parallel-syncs <master-name> <numslaves> 這個配置項指定了在發生failover主備切換時最多可以有多少個slave同時對新的master進行 同步,這個數字越小,完成failover所需的時間就越長,但是如果這個數字越大,就意味着越 多的slave因為replication而不可用。可以通過將這個值設為 1 來保證每次只有一個slave 處於不能處理命令請求的狀態。 sentinel failover-timeout <master-name> <milliseconds> failover-timeout 可以用在以下這些方面: 1. 同一個sentinel對同一個master兩次failover之間的間隔時間。 2. 當一個slave從一個錯誤的master那里同步數據開始計算時間。直到slave被糾正為向正確的master那里同步數據時。 3.當想要取消一個正在進行的failover所需要的時間。 4.當進行failover時,配置所有slaves指向新的master所需的最大時間。不過,即使過了這個超時,slaves依然會被正確配置為指向master,但是就不按parallel-syncs所配置的規則來了。
配置哨兵模式
cd /usr/local/redis
mkdir sentinel
cp sentinel.conf sentinel/
# master 由於主從設置了密碼,所以這里也需要設置 port 26379 daemonize no pidfile /var/run/redis-sentinel.pid logfile "/var/log/master.log" dir /tmp # # monitor 監控master IP地址和端口,最后的數字1 是有幾個哨兵確認即確認主下線 sentinel monitor mymaster 192.168.0.111 6379 1 # #修改心跳為30000毫秒 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel deny-scripts-reconfig yes sentinel auth-pass mymaster 123456
sentinel notification-script mymaster /usr/local/redis/sentinel/notify.sh
# slave1 port 26379 daemonize yes pidfile /var/run/redis-sentinel.pid logfile "/var/log/slave1.log" dir /tmp sentinel monitor mymaster 192.168.0.111 6380 1 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel deny-scripts-reconfig yes sentinel auth-pass mymaster 123456
sentinel notification-script mymaster /usr/local/redis/sentinel/notify.sh
# slave2 port 26379 daemonize yes pidfile /var/run/redis-sentinel.pid logfile "/var/log/slave1.log" dir /tmp sentinel monitor mymaster 192.168.0.111 6380 1 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel deny-scripts-reconfig yes sentinel auth-pass mymaster 123456
sentinel notification-script mymaster /usr/local/redis/sentinel/notify.sh
notify.sh:
# 配置當master發生轉移時進行郵件通知
# /bin/bash
TO="mail@qq.com"
SUBJECT="redis 發生故障轉移"
CONTEXT="redis 發生故障轉移"
echo -e $CONTEXT | mailx -s $SUBJECT $TO
啟動:
redis-sentinel /usr/local/redis/sentinel/sentinel.conf
驗證sentinel結果
[root@node1 sentinel]# redis-cli -p 26379 127.0.0.1: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=mymaster,status=ok,address=192.168.0.111:6380,slaves=2,sentinels=3 127.0.0.1:26379>
查看monitor 信息,包含publish ping info 等信息
[root@node2 redis]# redis-cli -h 192.168.0.112 -p 6380 192.168.0.112:6380> monitor OK 1611238079.243835 [0 192.168.0.111:6380] "PUBLISH" "__sentinel__:hello" "192.168.0.111,26379,2c35b4005313e08a1f63ae610f1c6b2e4fbdeb29,4,mymaster,192.168.0.111,6380,4" 1611238079.306039 [0 192.168.0.111:39986] "PING" 1611238079.319472 [0 192.168.0.111:6380] "PUBLISH" "__sentinel__:hello" "192.168.0.112,26379,5836276e4b4c9873f34306f9eaa954c24ce3a83f,4,mymaster,192.168.0.111,6380,4" 1611238079.371552 [0 192.168.0.112:50042] "PING" 1611238079.732581 [0 192.168.0.111:39986] "PUBLISH" "__sentinel__:hello" "192.168.0.111,26379,2c35b4005313e08a1f63ae610f1c6b2e4fbdeb29,4,mymaster,192.168.0.111,6380,4" 1611238079.951977 [0 192.168.0.110:39640] "PING" 1611238080.352478 [0 192.168.0.111:39986] "PING" 1611238080.407596 [0 192.168.0.112:50042] "PING" 1611238080.712552 [0 192.168.0.110:39640] "PUBLISH" "__sentinel__:hello" "192.168.0.110,26379,09ec92475178ccf00e52bdbfc9f71e4bab19e391,4,mymaster,192.168.0.111,6380,4" 1611238080.869619 [0 192.168.0.111:6380] "PUBLISH" "__sentinel__:hello" "192.168.0.110,26379,09ec92475178ccf00e52bdbfc9f71e4bab19e391,4,mymaster,192.168.0.111,6380,4" 1611238080.898855 [0 192.168.0.112:50042] "PUBLISH" "__sentinel__:hello" "192.168.0.112,26379,5836276e4b4c9873f34306f9eaa954c24ce3a83f,4,mymaster,192.168.0.111,6380,4" 1611238080.994489 [0 192.168.0.110:39640] "PING" 1611238081.292834 [0 192.168.0.111:6380] "PUBLISH" "__sentinel__:hello" "192.168.0.111,26379,2c35b4005313e08a1f63ae610f1c6b2e4fbdeb29,4,mymaster,192.168.0.111,6380,4" 1611238081.339470 [0 192.168.0.111:6380] "PUBLISH" "__sentinel__:hello" "192.168.0.112,26379,5836276e4b4c9873f34306f9eaa954c24ce3a83f,4,mymaster,192.168.0.111,6380,4" 1611238081.392597 [0 192.168.0.111:39986] "PING" 1611238081.454638 [0 192.168.0.112:50042] "PING" 1611238081.733629 [0 192.168.0.111:39986] "PUBLISH" "__sentinel__:hello" "192.168.0.111,26379,2c35b4005313e08a1f63ae610f1c6b2e4fbdeb29,4,mymaster,192.168.0.111,6380,4" 1611238082.073600 [0 192.168.0.110:39640] "PING" 1611238082.455256 [0 192.168.0.111:39986] "PING" 1611238082.511158 [0 192.168.0.112:50042] "PING" 1611238082.753551 [0 192.168.0.110:39640] "PUBLISH" "__sentinel__:hello" "192.168.0.110,26379,09ec92475178ccf00e52bdbfc9f71e4bab19e391,4,mymaster,192.168.0.111,6380,4" 1611238082.915633 [0 192.168.0.111:6380] "PUBLISH" "__sentinel__:hello" "192.168.0.110,26379,09ec92475178ccf00e52bdbfc9f71e4bab19e391,4,mymaster,192.168.0.111,6380,4" 1611238082.956576 [0 192.168.0.112:50042] "PUBLISH" "__sentinel__:hello" "192.168.0.112,26379,5836276e4b4c9873f34306f9eaa954c24ce3a83f,4,mymaster,192.168.0.111,6380,4" 1611238083.134109 [0 192.168.0.110:39640] "PING" 1611238083.312908 [0 192.168.0.111:6380] "PUBLISH" "__sentinel__:hello" "192.168.0.111,26379,2c35b4005313e08a1f63ae610f1c6b2e4fbdeb29,4,mymaster,192.168.0.111,6380,4" 1611238083.386855 [0 192.168.0.111:6380] "PUBLISH" "__sentinel__:hello" "192.168.0.112,26379,5836276e4b4c9873f34306f9eaa954c24ce3a83f,4,mymaster,192.168.0.111,6380,4" 1611238083.501301 [0 192.168.0.111:39986] "PING" 1611238083.541638 [0 192.168.0.112:50042] "PING" 1611238083.546508 [0 192.168.0.111:6380] "PING" 1611238083.738718 [0 192.168.0.111:39986] "PUBLISH" "__sentinel__:hello" "192.168.0.111,26379,2c35b4005313e08a1f63ae610f1c6b2e4fbdeb29,4,mymaster,192.168.0.111,6380,4" 1611238084.163607 [0 192.168.0.110:39640] "PING" 1611238084.510103 [0 192.168.0.111:39986] "PING" 1611238084.588757 [0 192.168.0.112:50042] "PING" 1611238084.791326 [0 192.168.0.110:39640] "PUBLISH" "__sentinel__:hello" "192.168.0.110,26379,09ec92475178ccf00e52bdbfc9f71e4bab19e391,4,mymaster,192.168.0.111,6380,4" 1611238084.940186 [0 192.168.0.111:6380] "PUBLISH" "__sentinel__:hello" "192.168.0.110,26379,09ec92475178ccf00e52bdbfc9f71e4bab19e391,4,mymaster,192.168.0.111,6380,4" 1611238084.963348 [0 192.168.0.112:50042] "PUBLISH" "__sentinel__:hello" "192.168.0.112,26379,5836276e4b4c9873f34306f9eaa954c24ce3a83f,4,mymaster,192.168.0.111,6380,4" 1611238085.226519 [0 192.168.0.110:39640] "PING"
測試:
redis主從正常的時候,只有主可以寫,從都不能寫,這是關閉主redis,可以查看日志發現轉移到slave節點了,可以在slave節點寫一個鍵 set k1 test
當原來的master啟動后,進去寫發現提示不能寫,get k1,發現鍵可以獲取到,已經從主變為從了
9.Redis-cluster集群
1.哨兵模式的缺陷 在哨兵模式中,仍然只有一個Master節點。當並發寫請求較大時,哨兵模式並不能緩解寫壓力。 我們知道只有主節點才具有寫能力,那如果在一個集群中,能夠配置多個主節點,是不是就可以緩解寫壓力了呢? 答:是的。這個就是redis-cluster集群模式。 2.Redis-cluster集群概念 (1)由多個Redis服務器組成的分布式網絡服務集群; (2)集群之中有多個Master主節點,每一個主節點都可讀可寫; (3)節點之間會互相通信,兩兩相連; (4)Redis集群無中心節點。 3.集群節點復制 在Redis-Cluster集群中,可以給每一個主節點添加從節點,主節點和從節點直接遵循主從模型的特性。 當用戶需要處理更多讀請求的時候,添加從節點可以擴展系統的讀性能。 4.故障轉移 Redis集群的主節點內置了類似Redis Sentinel的節點故障檢測和自動故障轉移功能,當集群中的某個主節點下線時,集群中的其他在線主節點會注意到這一點,並對已下線的主節點進行故障轉移。 集群進行故障轉移的方法和Redis Sentinel進行故障轉移的方法基本一樣,不同的是,在集群里面,故障轉移是由集群中其他在線的主節點負責進行的,所以集群不必另外使用Redis Sentinel。 5.集群分片策略 Redis-cluster分片策略,是用來解決key存儲位置的 集群將整個數據庫分為16384個槽位slot,所有key-value數據都存儲在這些slot中的某一個上。一個slot槽位可以存放多個數據,key的槽位計算公式為:slot_number=crc16(key)%16384,其中crc16為16位的循環冗余校驗和函數。 集群中的每個主節點都可以處理0個至16383個槽,當16384個槽都有某個節點在負責處理時,集群進入上線狀態,並開始處理客戶端發送的數據命令請求。 6.集群redirect轉向 由於Redis集群無中心節點,請求會隨機發給任意主節點; 主節點只會處理自己負責槽位的命令請求,其它槽位的命令請求,該主節點會返回客戶端一個轉向錯誤; 客戶端根據錯誤中包含的地址和端口重新向正確的負責的主節點發起命令請求。
10.集群搭建配置(系統優化參數請自行處理)
# 系統優化沒做到位,redis啟動后有一些warning報警,可以處理 TCP監聽隊列大小 即TCP listen的backlog大小,“/proc/sys/net/core/somaxconn”的默認值一般較小如128,需要修改大一點,比如改成32767。立即生效還可以使用命令:sysctl -w net.core.somaxconn=32767。 要想永久生效,需要在文件/etc/sysctl.conf中增加一行:net.core.somaxconn = 32767,然后執行命令“sysctl -p”以生效。 Redis配置項tcp-backlog的值不能超過somaxconn的大小。 OOM相關:vm.overcommit_memory “/proc/sys/vm/overcommit_memory”默認值為0,表示不允許申請超過CommitLimmit大小的內存。可以設置為1關閉Overcommit,設置方法請參照net.core.somaxconn完成。 /sys/kernel/mm/transparent_hugepage/enabled 默認值為“[always] madvise never”,建議設置為never,以開啟內核的“Transparent Huge Pages (THP)”特性,設置后redis進程需要重啟。為了永久生效,請將“echo never > /sys/kernel/mm/transparent_hugepage/enabled”加入到文件/etc/rc.local中。 什么是Transparent Huge Pages?為提升性能,通過大內存頁來替代傳統的4K頁,使用得管理虛擬地址數變少,加快從虛擬地址到物理地址的映射,以及摒棄內存頁面的換入換出以提高內存的整體性能。內核Kernel將程序緩存內存中,每頁內存以2M為單位。相應的系統進程為khugepaged。 在Linux中,有兩種方式使用Huge Pages,一種是2.6內核引入的HugeTLBFS,另一種是2.6.36內核引入的THP。HugeTLBFS主要用於數據庫,THP廣泛應用於應用程序。 一般可以在rc.local或/etc/default/grub中對Huge Pages進行設置。
# 環境 centos 7.9: 192.168.0.111 redis端口:7001 7002 7003 centos 7.9: 192.168.0.112 redis端口:7004 7005 7006 # 在對應服務器新建目錄 cd /usr/local/redis/ mkdir conf && cd conf && mkdir 7001 7002 7003 # 另外一台服務器對應新建 # 拷貝也拷貝到對應目錄下 cp /usr/local/redis/redis.conf /usr/local/redis/7001/ # 配置 bind 192.168.0.111 daemon yes port 7001 pidfile "/var/run/redis_7001.pid" logfile "/usr/local/redis/conf/7001/redis.log" dir "/usr/local/redis/conf/7001/" appendonly yes # 打開集群:yes表示以集群方式運行 cluster-enabled yes # 默認放在dir指定的目錄,注意不能包含目錄,純文件名,為redis-server進程自動維護,不能手工修改 cluster-config-file nodes-7001.conf # 2台服務器其余的端口和配置也按照相應的修改 # 啟動redis腳本 # start_cluster.sh #!/bin/bash cd /usr/local/redis/conf/7001/ && /usr/local/redis/src/redis-server /usr/local/redis/conf/7001/7001.conf cd /usr/local/redis/conf/7002/ && /usr/local/redis/src/redis-server /usr/local/redis/conf/7002/7002.conf cd /usr/local/redis/conf/7003/ && /usr/local/redis/src/redis-server /usr/local/redis/conf/7003/7003.conf # 啟動redis
10.1執行創建集群命令
[root@node1 conf]# /usr/local/redis/src/redis-cli --cluster create 192.168.0.111:7001 192.168.0.111:7002 192.168.0.111:7003 192.168.0.112:7004 192.168.0.112:7005 192.168.0.112:7006 --cluster-replicas 1 # --cluster-replicas 1 表示主從配置比,1表示的是1:1,前三個是主,后三個是從 # 若配置文件中設置的密碼,則還需要加上-a passwod >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 192.168.0.112:7006 to 192.168.0.111:7001 Adding replica 192.168.0.111:7003 to 192.168.0.112:7004 Adding replica 192.168.0.112:7005 to 192.168.0.111:7002 M: f34090f7f97229ee11bbc33decc1a572a508f217 192.168.0.111:7001 slots:[0-5460] (5461 slots) master M: eb7e75bc30912b79c222422696d0ce7401061d24 192.168.0.111:7002 slots:[10923-16383] (5461 slots) master S: e1c603a80d98724c1e9203f22e13554cd6c90836 192.168.0.111:7003 replicates 093b4824954ef39f6aaebc549ccb778a779f6141 M: 093b4824954ef39f6aaebc549ccb778a779f6141 192.168.0.112:7004 slots:[5461-10922] (5462 slots) master S: 5d8919c87935443d6d0398804cf7c3633b37c725 192.168.0.112:7005 replicates eb7e75bc30912b79c222422696d0ce7401061d24 S: bf54081536141ef94652d9decfd8ade8fd07313c 192.168.0.112:7006 replicates f34090f7f97229ee11bbc33decc1a572a508f217 Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join . >>> Performing Cluster Check (using node 192.168.0.111:7001) M: f34090f7f97229ee11bbc33decc1a572a508f217 192.168.0.111:7001 slots:[0-5460] (5461 slots) master 1 additional replica(s) M: eb7e75bc30912b79c222422696d0ce7401061d24 192.168.0.111:7002 slots:[10923-16383] (5461 slots) master 1 additional replica(s) M: 093b4824954ef39f6aaebc549ccb778a779f6141 192.168.0.112:7004 slots:[5461-10922] (5462 slots) master 1 additional replica(s) S: bf54081536141ef94652d9decfd8ade8fd07313c 192.168.0.112:7006 slots: (0 slots) slave replicates f34090f7f97229ee11bbc33decc1a572a508f217 S: 5d8919c87935443d6d0398804cf7c3633b37c725 192.168.0.112:7005 slots: (0 slots) slave replicates eb7e75bc30912b79c222422696d0ce7401061d24 S: e1c603a80d98724c1e9203f22e13554cd6c90836 192.168.0.111:7003 slots: (0 slots) slave replicates 093b4824954ef39f6aaebc549ccb778a779f6141 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
10.2 查詢集群信息
[root@node1 7001]# redis-cli -c -h 192.168.0.111 -p 7001 cluster nodes eb7e75bc30912b79c222422696d0ce7401061d24 192.168.0.111:7002@17002 master - 0 1611241903616 2 connected 10923-16383 093b4824954ef39f6aaebc549ccb778a779f6141 192.168.0.112:7004@17004 master - 0 1611241902000 4 connected 5461-10922 bf54081536141ef94652d9decfd8ade8fd07313c 192.168.0.112:7006@17006 slave f34090f7f97229ee11bbc33decc1a572a508f217 0 1611241902611 6 connected f34090f7f97229ee11bbc33decc1a572a508f217 192.168.0.111:7001@17001 myself,master - 0 1611241901000 1 connected 0-5460 5d8919c87935443d6d0398804cf7c3633b37c725 192.168.0.112:7005@17005 slave eb7e75bc30912b79c222422696d0ce7401061d24 0 1611241901603 5 connected e1c603a80d98724c1e9203f22e13554cd6c90836 192.168.0.111:7003@17003 slave 093b4824954ef39f6aaebc549ccb778a779f6141 0 1611241904623 4 connected
參數說明: -c:表示以集群方式連接惹redis -h:指定IP地址 -p:指定端口 cluster nodes:查詢集群節點信息 cluster info:查詢集群狀態信息
查詢集群各類狀態

[root@node1 redis]# redis-cli -h 192.168.0.111 -c -p 7001 192.168.0.111:7001> cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:1 cluster_stats_messages_ping_sent:416 cluster_stats_messages_pong_sent:403 cluster_stats_messages_sent:819 cluster_stats_messages_ping_received:398 cluster_stats_messages_pong_received:416 cluster_stats_messages_meet_received:5 cluster_stats_messages_received:819 192.168.0.111:7001> cluster nodes bc053eba10e250a7cdd6dbf399bc962e27f5d866 192.168.0.111:7002@17002 master - 0 1611318904748 2 connected 10923-16383 96ed924479ba846bf3e82ef8669dc34082c9c09b 192.168.0.111:7003@17003 slave cc381563074a7779a0ad250b83301b81d50ba2d6 0 1611318904000 4 connected e5700897b67917699bb68f22dae624300c2cc042 192.168.0.111:7001@17001 myself,master - 0 1611318899000 1 connected 0-5460 cc381563074a7779a0ad250b83301b81d50ba2d6 192.168.0.112:7004@17004 master - 0 1611318905756 4 connected 5461-10922 200087a0430621a44d42dae772413ce47cc7ba20 192.168.0.112:7006@17006 slave e5700897b67917699bb68f22dae624300c2cc042 0 1611318903742 6 connected f0eaffe55a1543445231a22574fce085299eb383 192.168.0.112:7005@17005 slave bc053eba10e250a7cdd6dbf399bc962e27f5d866 0 1611318903000 5 connected 192.168.0.111:7001> set name cxiong -> Redirected to slot [5798] located at 192.168.0.112:7004 OK 192.168.0.112:7004> set sex 1 -> Redirected to slot [2584] located at 192.168.0.111:7001 OK 192.168.0.111:7001> set addr 10086 -> Redirected to slot [12790] located at 192.168.0.111:7002 OK 192.168.0.111:7002> get name -> Redirected to slot [5798] located at 192.168.0.112:7004 "cxiong" 192.168.0.112:7004> get addr -> Redirected to slot [12790] located at 192.168.0.111:7002 "10086" 192.168.0.111:7002> get sex -> Redirected to slot [2584] located at 192.168.0.111:7001 "1"
10.3 redis cluster集群重新啟動
暫時未知
10.4 redis-cli 集群命令幫助
[root@node1 redis]# redis-cli --cluster help Cluster Manager Commands: create host1:port1 ... hostN:portN --cluster-replicas <arg> check host:port --cluster-search-multiple-owners info host:port fix host:port --cluster-search-multiple-owners reshard host:port --cluster-from <arg> --cluster-to <arg> --cluster-slots <arg> --cluster-yes --cluster-timeout <arg> --cluster-pipeline <arg> --cluster-replace rebalance host:port --cluster-weight <node1=w1...nodeN=wN> --cluster-use-empty-masters --cluster-timeout <arg> --cluster-simulate --cluster-pipeline <arg> --cluster-threshold <arg> --cluster-replace add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id <arg> del-node host:port node_id call host:port command arg arg .. arg set-timeout host:port milliseconds import host:port --cluster-from <arg> --cluster-copy --cluster-replace help For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
10.5 測試故障性轉移
在故障期間,獲取key值都可以在別的nodes里獲取到
# 在此測試期間,為了觸發故障轉移,我們可以做的最簡單的事情(也就是在分布式系統中可能出現的語義上最簡單的故障)是使單個進程崩潰 [root@Master conf]# redis-cli -h 192.168.0.112 -p 7001 debug segfault Error: Server closed the connection # redis-cli -h 192.168.0.112 -p 7004 debug segfault [root@node1 7003]# redis-cli -c -h 192.168.0.111 -p 7002 192.168.0.111:7002> cluster nodes bc053eba10e250a7cdd6dbf399bc962e27f5d866 192.168.0.111:7002@17002 myself,master - 0 1611320054000 2 connected 10923-16383 cc381563074a7779a0ad250b83301b81d50ba2d6 192.168.0.112:7004@17004 master,fail - 1611319488239 1611319486221 4 disconnected 96ed924479ba846bf3e82ef8669dc34082c9c09b 192.168.0.111:7003@17003 master - 0 1611320058188 7 connected 5461-10922 200087a0430621a44d42dae772413ce47cc7ba20 192.168.0.112:7006@17006 master - 0 1611320057174 8 connected 0-5460 f0eaffe55a1543445231a22574fce085299eb383 192.168.0.112:7005@17005 slave bc053eba10e250a7cdd6dbf399bc962e27f5d866 0 1611320056159 5 connected e5700897b67917699bb68f22dae624300c2cc042 192.168.0.111:7001@17001 master,fail - 1611319646927 1611319645000 1 disconnected
重新啟動故障redis
192.168.0.111:7002> cluster nodes bc053eba10e250a7cdd6dbf399bc962e27f5d866 192.168.0.111:7002@17002 myself,master - 0 1611320358000 2 connected 10923-16383 cc381563074a7779a0ad250b83301b81d50ba2d6 192.168.0.112:7004@17004 slave 96ed924479ba846bf3e82ef8669dc34082c9c09b 0 1611320359379 7 connected 96ed924479ba846bf3e82ef8669dc34082c9c09b 192.168.0.111:7003@17003 master - 0 1611320360388 7 connected 5461-10922 200087a0430621a44d42dae772413ce47cc7ba20 192.168.0.112:7006@17006 master - 0 1611320358000 8 connected 0-5460 f0eaffe55a1543445231a22574fce085299eb383 192.168.0.112:7005@17005 slave bc053eba10e250a7cdd6dbf399bc962e27f5d866 0 1611320359000 5 connected e5700897b67917699bb68f22dae624300c2cc042 192.168.0.111:7001@17001 slave 200087a0430621a44d42dae772413ce47cc7ba20 0 1611320359000 8 connected
10.6 集群管理
# 1.添加新的主節點 redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-master-id node_id
# 例子說明
# 給已存在的192.168.0.111:7001端口再添加一個 new_host:new_port為要新添加的主節點IP和端口,此處是192.168.0.110:7007 existing_host:existing_port表示的是已存在的一個主節點的IP和端口,這個可以從上述的節點信息中查看到,根據slots槽數,7003端口對應的節點槽數是10923-16383,16383表示的是最后的槽數 --cluster-master-id表示的是最后一個主節點的節點id,表示的是新添加的主節點要在這個節點后面 [root@node1 ~]# redis-cli --cluster add-node 192.168.0.110:7007 192.168.0.111:7001 --cluster-master-id e5700897b67917699bb68f22dae624300c2cc042 >>> Adding node 192.168.0.110:7007 to cluster 192.168.0.111:7001 >>> Performing Cluster Check (using node 192.168.0.111:7001) S: e5700897b67917699bb68f22dae624300c2cc042 192.168.0.111:7001 slots: (0 slots) slave replicates 200087a0430621a44d42dae772413ce47cc7ba20 M: 96ed924479ba846bf3e82ef8669dc34082c9c09b 192.168.0.111:7003 slots:[5461-10922] (5462 slots) master 1 additional replica(s) M: 200087a0430621a44d42dae772413ce47cc7ba20 192.168.0.112:7006 slots:[0-5460] (5461 slots) master 1 additional replica(s) S: f0eaffe55a1543445231a22574fce085299eb383 192.168.0.112:7005 slots: (0 slots) slave replicates bc053eba10e250a7cdd6dbf399bc962e27f5d866 M: bc053eba10e250a7cdd6dbf399bc962e27f5d866 192.168.0.111:7002 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: cc381563074a7779a0ad250b83301b81d50ba2d6 192.168.0.112:7004 slots: (0 slots) slave replicates 96ed924479ba846bf3e82ef8669dc34082c9c09b [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. >>> Send CLUSTER MEET to node 192.168.0.110:7007 to make it join the cluster. [OK] New node added correctly. # 查看 192.168.0.110:7007> cluster nodes 99aa44c17491637deecbddda5bbfc80890b4daf3 192.168.0.110:7007@17007 myself,slave bc053eba10e250a7cdd6dbf399bc962e27f5d866 0 1611323597000 1 connected f0eaffe55a1543445231a22574fce085299eb383 192.168.0.112:7005@17005 slave bc053eba10e250a7cdd6dbf399bc962e27f5d866 0 1611323596468 2 connected e5700897b67917699bb68f22dae624300c2cc042 192.168.0.111:7001@17001 slave 200087a0430621a44d42dae772413ce47cc7ba20 0 1611323593000 8 connected 200087a0430621a44d42dae772413ce47cc7ba20 192.168.0.112:7006@17006 master - 0 1611323595000 8 connected 0-5460 bc053eba10e250a7cdd6dbf399bc962e27f5d866 192.168.0.111:7002@17002 master - 0 1611323594451 2 connected 10923-16383 96ed924479ba846bf3e82ef8669dc34082c9c09b 192.168.0.111:7003@17003 master - 0 1611323597476 7 connected 5461-10922 cc381563074a7779a0ad250b83301b81d50ba2d6 192.168.0.112:7004@17004 slave 96ed924479ba846bf3e82ef8669dc34082c9c09b 0 1611323595460 7 connected
# 2.hash槽重新分配
# 添加完新節點后,需要對新添加的主節點進行hash槽重新分配,這樣該主節點才能存儲數據,redis共有16384個槽。(node_id必須都是主節點)
redis-cli --cluster reshard host:port --cluster-from node_id --cluster-to node_id --cluster-slots <args> --cluster-yes
# 例子說明 host:port表示的是新添加的那個主節點IP和端口,此處表示的是IP:7007(由於測試變為slave了,結果添加不了) --cluster-from node_id表示的是集群第一個主節點的節點id,這個可以現有集群的slots槽數分配看出,此處表示的是7001端口對應的節點 --cluster-to node_id表示的是集群最后一個主節點的節點id,也就是新添加的那個主節點id,此處表示的是7007端口對應的節點 --cluster-slots 500表示的是給新主節點分配多少,此處500表示是分配從0-499個slots槽數,若不加上這個會讓手動輸入 --cluster-yes表示的是自動應答為yes,若不加上這個會讓手動輸入yes,表示同意此次分配
# 3.添加新從節點 redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id node_id 例如:redis-cli --cluster add-node 192.168.0.110:7008 192.168.0.111:7002 --cluster-slave --cluster-master-id bc053eba10e250a7cdd6dbf399bc962e27f5d866
cluster nodes:03033fcdade6b2bb1663852216003e8168e064ea 192.168.0.110:7008@17008 slave bc053eba10e250a7cdd6dbf399bc962e27f5d866 0 1611324674580 2 connected
# 4.刪除節點 redis-cli --cluster del-node host:port node_id
例如:
[root@Master conf]# redis-cli --cluster del-node 192.168.0.110:7008 03033fcdade6b2bb1663852216003e8168e064ea
>>> Removing node 03033fcdade6b2bb1663852216003e8168e064ea from cluster 192.168.0.110:7008
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
刪除后可以發現剛添加的從節點已經小時了
# 5.刪除后從其他節點還是可以看到這個節點,需要執行其他命令,這樣這個節點就看不見了
192.168.0.111:7001>cluster forget 03033fcdade6b2bb1663852216003e8168e064ea
11.人工手動切換主從
在需要變為主節點的slave上執行
192.168.0.112:7005> cluster failover OK # 然后查看就可以發現從slave 變為myself,master
f0eaffe55a1543445231a22574fce085299eb383 192.168.0.112:7005@17005 myself,master - 0 1611325331000 11 connected 10923-16383
12.大壓力下redis參數調整要點
為何大壓力下要這樣調整?
最重要的原因之一Redis的主從復制,兩者復制共享同一線程,雖然是異步復制的,但因為是單線程,所以也十分有限。如果主從間的網絡延遲不是在0.05左右,比如達到0.6,甚至1.2等,那么情況是非常糟糕的,因此同一Redis集群一定要部署在同一機房內。
這些參數的具體值,要視具體的壓力而定,而且和消息的大小相關,比如一條200~500KB的流水數據可能比較大,主從復制的壓力也會相應增大,而10字節左右的消息,則壓力要小一些。大壓力環境中開啟appendfsync是十分不可取的,容易導致整個集群不可用,在不可用之前的典型表現是QPS毛刺明顯。
這么做的目的是讓Redis集群盡可能的避免master正常時觸發主從切換,特別是容納的數據量很大時,和大壓力結合在一起,集群會雪崩
參數 |
建議最小值 |
說明 |
repl-ping-slave-period |
10 |
每10秒ping一次 |
repl-timeout |
60 |
60秒超時,也就是ping十次 |
cluster-node-timeout |
15000 |
|
repl-backlog-size |
1GB |
Master對slave的隊列大小 |
appendfsync |
no |
讓系統自動刷 |
save |
|
大壓力下,調大參數值,以減少寫RDB帶來的壓力: "900 20 300 200 60 200000" |
appendonly |
|
對於隊列,建議單獨建立集群,並且設置該值為no |