前面的文章已經介紹了redis作為緩存數據庫的說明,本文主要說下redis主從復制及集群管理配置的操作記錄:
Redis主從復制(目前redis僅支持主從復制模式,可以支持在線備份、讀寫分離等功能。)
1)Redis的復制功能是支持多個數據庫之間的數據同步。一類是主數據庫(master),一類是從數據庫(slave),主數據庫可以進行讀寫操作,當發生寫操作的時候自動 將數據同步到從數據庫,而從數據庫一般是只讀的,並接收主數據庫同步過來的數據,一個主數據庫可以有多個從數據庫,而一個從數據庫只能有一個主數據庫。 2)通過redis的復制功能可以很好的實現數據庫的讀寫分離,提高服務器的負載能力。主數據庫主要進行寫操作,而從數據庫負責讀操作。
Redis主從復制流程圖

復制過程:
1)當一個從數據庫啟動時,會向主數據庫發送sync命令, 2)主數據庫接收到sync命令后會開始在后台保存快照(執行rdb操作),並將保存期間接收到的命令緩存起來 3)當快照完成后,redis會將快照文件和所有緩存的命令發送給從數據庫。 4)從數據庫收到后,會載入快照文件並執行收到的緩存的命令。
下面簡單記錄下Redis主從復制的操作記錄:
1)機器信息 Redis主從結構支持一主多從,這里我使用一主兩從(一主一從也行,配置一樣) 主節點 182.48.115.236 master-node 從節點 182.48.115.237 slave-node1 從節點 182.48.115.238 slave-node2 關閉三個節點機的iptables防火牆和selinux 2)安裝redis 三台節點機的安裝步驟一樣 [root@master-node ~]# wget http://download.redis.io/redis-stable.tar.gz [root@master-node ~]# tar -zvxf redis-stable.tar.gz [root@master-node ~]# cd redis-stable [root@master-node redis-stable]# make [root@master-node redis-stable]# cd src/ [root@master-node src]# cp redis-server redis-cli redis-check-aof redis-check-rdb redis-sentinel redis-trib.rb /usr/local/bin/ 然后新建目錄,存放配置文件 [root@master-node src]# mkdir /etc/redis [root@master-node src]# mkdir /var/redis [root@master-node src]# mkdir /var/redis/log [root@master-node src]# mkdir /var/redis/run [root@master-node src]# mkdir /var/redis/redis 在redis解壓根目錄中找到配置文件模板 [root@master-node src]# cd ../ [root@master-node redis-stable]# cp redis.conf /etc/redis/redis.conf 設置啟動腳本 [root@master-node redis-stable]# cp utils/redis_init_script /etc/init.d/redis [root@master-node redis-stable]# chmod 755 /etc/init.d/redis 修改腳本pid及conf路徑為實際路徑 [root@master-node redis-stable]# vim /etc/init.d/redis ...... REDISPORT=6379 EXEC=/usr/local/bin/redis-server CLIEXEC=/usr/local/bin/redis-cli PIDFILE=/var/redis/run/redis_6379.pid CONF="/etc/redis/redis.conf" ....... 3)主從復制配置 master-node [root@master-node ~]# vim /etc/redis/redis.conf ....... port 6379 ....... daemonize yes //這個修改為yes ....... bind 0.0.0.0 //綁定的主機地址。說明只能通過這個ip地址連接本機的redis。最好綁定0.0.0.0;注意這個不能配置成127.0.0.1,否則復制會失敗!用0.0.0.0或者本機ip地址都可以 ....... pidfile /var/redis/run/redis_6379.pid ....... logfile /var/redis/log/redis_6379.log ....... dir /var/redis/redis #redis數據目錄 ....... appendonly yes #啟用AOF持久化方式 appendfilename "appendonly.aof" #AOF文件的名稱,默認為appendonly.aof appendfsync everysec #每秒鍾強制寫入磁盤一次,在性能和持久化方面做了很好的折中,是受推薦的方式。 ..... save 900 1 #啟用RDB快照功能,默認就是啟用的 save 300 10 save 60 10000 #即在多少秒的時間內,有多少key被改變的數據添加到.rdb文件里 ....... dbfilename dump.rdb #快照文件名稱 ...... slave-node1和slave-node2兩個從節點相比於master-node主節點的redis.conf配置,只是多了下面一行配置,其它都一樣: slaveof 182.48.115.236 6379 啟動三個節點的redis(啟動命令一樣) [root@master-node ~]# /etc/init.d/redis start Starting Redis server... [root@master-node ~]# lsof -i:6379 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME redis-ser 10475 root 4u IPv4 88640 0t0 TCP localhost:6379 (LISTEN) 登陸主節點master-node的redis,查看狀態 [root@master-node ~]# redis-cli -h 127.0.0.1 -p 6379 //使用182.48.115.236也可以登錄,或者直接使用redis-cli也可以登錄 127.0.0.1:6379> info ...... ...... # Replication role:master //節點在集群中的狀態 connected_slaves:2 //slave節點的個數 slave0:ip=182.48.115.238,port=6379,state=online,offset=1,lag=1 slave1:ip=182.48.115.237,port=6379,state=online,offset=1,lag=1 ........ 登錄從節點slave-node1的redis,查看狀態 [root@slave-node1 ~]# redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> info ....... ....... # Replication role:slave master_host:182.48.115.236 master_port:6379 master_link_status:up ...... 登錄從節點slave-node2的redis,查看狀態 [root@slave-node2 ~]# redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> info ...... # Replication role:slave master_host:182.48.115.236 master_port:6379 master_link_status:up ...... 4)測試數據同步 主節點master-node上寫入新數據 [root@master-node ~]# redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> set name wangshibo OK 127.0.0.1:6379> get name "wangshibo" 然后到兩台從節點上查看是否同步了上面寫入的數據 [root@slave-node1 ~]# redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> get name "wangshibo" [root@slave-node2 ~]# redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> get name "wangshibo" redis主從復制默認是讀寫分離的,即: 主節點上可以讀寫操作;從節點上只能進行讀操作,不能寫數據 [root@slave-node1 ~]# redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> set name huanqiu (error) READONLY You can't write against a read only slave. [root@slave-node2 ~]# redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> set name huanqiu (error) READONLY You can't write against a read only slave. 5)主從切換 5.1)停止主節點master-node的redis [root@master-node ~]# redis-cli -h 127.0.0.1 -p 6379 shutdown [root@master-node ~]# redis-cli -h 127.0.0.1 -p 6379 Could not connect to Redis at 127.0.0.1:6379: Connection refused Could not connect to Redis at 127.0.0.1:6379: Connection refused 將從節點slave-node1的redis設成主redis [root@slave-node1 ~]# redis-cli -h 127.0.0.1 -p 6379 slaveof NO ONE //這條命了只是臨時將該節點設置為主節點;當redis重啟后,就會失效;可以登錄redis,通過info信息查看! OK [root@slave-node1 ~]# redis-cli -h 127.0.0.1 -p 6379 //變為主redis后,slave-node1就可以進行寫入操作了 127.0.0.1:6379> set name huanqiu OK 127.0.0.1:6379> info ...... # Replication role:master //可知已經變成master主節點了 connected_slaves:0 master_repl_offset:0 這時候master-node節點已經故障了,而另一個從節點slave-node2還跟它有主從關系。此時slave-node1已經變成主redis了,所以可以將slave-node2的主從關系中的主節點 配置修改為slave-node1(即182.48.115.237) 5.2)原來的主redis恢復正常了,要重新切換回去 比如原來的主redis節點master-node現在恢復了 [root@master-node ~]# /etc/init.d/redis start Starting Redis server... [root@master-node ~]# redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> info ...... # Replication role:master //原來的主節點恢復了,發現只有一個從節點save-node2。另一個從節點slave-node1在master-node故障期間臨時變為主節點 connected_slaves:1 slave0:ip=182.48.115.238,port=6379,state=online,offset=1,lag=0 ...... 那么現在要重新將主節點切換回去。步驟如下: a)登錄臨時切換的主節點slave-node1 [root@slave-node1 ~]# redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> set name hahahha OK 127.0.0.1:6379> get name "hahahha" 127.0.0.1:6379> save //將數據保存 OK b)將現在的主redis(即slave-node1節點,臨時設置的主節點)根目錄下app文件和dump.rdb文件拷貝覆蓋到原來主redis的根目錄(覆蓋前將原來主redis下的持久化文件備份下) [root@slave-node1 ~]# rsync -e "ssh -p22" -avpgolr /var/redis/redis/dump.rdb 182.48.115.236:/var/redis/redis/ [root@slave-node1 ~]# rsync -e "ssh -p22" -avpgolr /var/redis/redis/appendonly.aof 182.48.115.236:/var/redis/redis/ c)重啟原來的主redis(即master-node節點) [root@master-node ~]# /etc/init.d/redis stop [root@master-node ~]# /etc/init.d/redis start d)在現在的主redis(即slave-node1)中切換(或者直接重啟該節點的redis,因為redis.conf文件中已經配置了;如果不想重啟redis,就使用下面的命令) [root@slave-node1 ~]# redis-cli -h 127.0.0.1 -p 6379 slaveof 182.48.115.236 6379 OK e)登錄原來的主redis(也就是master-node)查看 [root@master-node ~]# redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> info ....... # Replication role:master connected_slaves:2 slave0:ip=182.48.115.237,port=6379,state=online,offset=1,lag=0 slave1:ip=182.48.115.238,port=6379,state=online,offset=1,lag=0 master_repl_offset:1 ...... ------------------------------------------------------------------------------------------------------------------ 注意事項 如果使用主從復制,那么要確保你的master激活了持久化,或者確保它不會在當掉后自動重啟,原因: a)slave是master的完整備份,因此如果master通過一個空數據集重啟,slave也會被清掉。 b)在配置redis復制功能的時候,如果主數據庫設置了密碼,需要在從數據的配置文件中通過masterauth參數設置主數據庫的密碼,這樣從數據庫在連接 主數據庫時就會自動使用auth命令認證了。相當於做了一個免密碼登錄。(我上面的例子中沒有設置密碼)
Redis的主從自動切換(failover)可以通過Redis自帶的Sentinel工具來實現(具體操作這里就先不介紹了)。redis的sentinel系統用於管理多個redis服務器,
該系統主要執行三個任務:監控、提醒、自動故障轉移。
1)監控(Monitoring): Redis Sentinel實時監控主服務器和從服務器運行狀態,並且實現自動切換。
2)提醒(Notification):當被監控的某個 Redis 服務器出現問題時, Redis Sentinel 可以向系統管理員發送通知, 也可以通過 API 向其他程序發送通知。
3)自動故障轉移(Automatic failover): 當一個主服務器不能正常工作時,Redis Sentinel 可以將一個從服務器升級為主服務器, 並對其他從服務器進行配置,
讓它們使用新的主服務器。當應用程序連接Redis 服務器時, Redis Sentinel會告之新的主服務器地址和端口。
注意:
在使用sentinel監控主從節點的時候,從節點需要是使用動態方式配置的,如果直接修改配置文件,后期sentinel實現故障轉移的時候會出問題。
------------------------------------------------------------------------------------------------------------------------------------------------
Redis默認只支持主從模式,不支持主主模式,可以使用SSDB主主模式代替Redis實現主主同步環境。SSDB是一個快速的用來存儲十億級別列表數據的開源 NoSQL 數據庫。支持Key-value, Keyhashmap, Key-zset(sorted set) 等數據結構,十分適合存儲數億條級別的列表, 排序表等集合數據, 是Redis的替代和增強方案。
SSDB特性:
1)替代 Redis 數據庫, Redis 的100倍容量 2)LevelDB 網絡支持, 使用C/C++ 開發 3)Redis API 兼容, 支持 Redis 客戶端 4)適合存儲集合數據, 如 list, hash, zset... 5)客戶端 API 支持的語言包括: C++, PHP, Python,Cpy,Java,Nodejs,Ruby, Go等 6)持久化的隊列服務 7)主從復制,支持雙主(雙master)和多主架構, 負載均衡 8)圖形化管理工具(phpssdbadmin)
SSDB的主從同步策略非常簡單, 就是把主(Master)上的所有寫操作(Binlogs), 在從(Slave)上再執行一遍. MySQL 的主從同步也是一樣. 而多主可以理解為互為主從.
SSDB的雙主和多主配置
SSDB 數據庫是支持雙主(雙 Master)和多主架構的. 而且, 我們的應用也是部署雙主架構, 但當作單主來用. 也就是說, 平時只往其中一個寫, 當出現故障時, 整體切換到另一個主上面. 如果應用層已經解決了數據拆分, 也即不會兩個節點同時操作一個 key, 那么就可以放心使用雙主同時寫入.
SSDB 雙主的配置非常簡單:
server1服務器
replication:
slaveof:
id: svc_2
# sync|mirror, default is sync
type: mirror
ip: 192.168.1.10
port: 8888
server2服務器
replication:
slaveof:
id: svc_1
# sync|mirror, default is sync
type: mirror
ip: 192.168.1.11
port: 8888
只需要將type設置為mirror, 然后每個節點各指向對方即可。如果是多主, 則每個節點要指向其它 n-1 個節點。
SSDB 主主同步模式部署記錄
SSDB主主模式的部署記錄:
182.48.115.236 master-node1
182.48.115.237 master-node2
1)安裝SSDB(在兩個節點機上安裝步驟一樣,如下)
[root@master-node1 ~]# mkdir -p /home/slim/ssdb
[root@master-node1 ~]# wget https://github.com/ideawu/ssdb/archive/master.zip
[root@master-node1 ~]# unzip master.zip
[root@master-node1 ~]# cd ssdb-master/
[root@master-node1 ssdb-master]# make PREFIX=/home/slim/ssdb
[root@master-node1 ssdb-master]# make PREFIX=/home/slim/ssdb install
2)主主模式配置
master-node1節點上的配置
[root@master-node1 ~]# cd /home/slim/ssdb/
[root@master-node1 ssdb]# cp ssdb.conf ssdb.conf.bak
[root@master-node1 ssdb]# vim ssdb.conf
# ssdb-server config
# MUST indent by TAB!
# relative to path of this file, directory must exists
work_dir = ./var
pidfile = ./var/ssdb.pid
server:
ip: 182.48.115.236
port: 8888
# bind to public ip
#ip: 0.0.0.0
# format: allow|deny: all|ip_prefix
# multiple allows or denys is supported
#deny: all
#allow: 127.0.0.1
#allow: 192.168
# auth password must be at least 32 characters
#auth: very-strong-password
#readonly: yes
replication:
binlog: yes
# Limit sync speed to *MB/s, -1: no limit
sync_speed: -1
slaveof:
# to identify a master even if it moved(ip, port changed)
# if set to empty or not defined, ip:port will be used.
id: svc_1
# sync|mirror, default is sync
type: mirror
host: 182.48.115.237
port: 8888
logger:
level: debug
output: log.txt
rotate:
size: 1000000000
leveldb:
# in MB
cache_size: 500
# in MB
write_buffer_size: 64
# in MB/s
compaction_speed: 1000
# yes|no
compression: yes
master-node2節點上的配置
[root@master-node2 ~]# cd /home/slim/ssdb/
[root@master-node2 ssdb]# cp ssdb.conf ssdb.conf.bak
[root@master-node2 ssdb]# vim ssdb.conf
# ssdb-server config
# MUST indent by TAB!
# relative to path of this file, directory must exists
work_dir = ./var
pidfile = ./var/ssdb.pid
server:
ip: 182.48.115.237
port: 8888
# bind to public ip
#ip: 0.0.0.0
# format: allow|deny: all|ip_prefix
# multiple allows or denys is supported
#deny: all
#allow: 127.0.0.1
#allow: 192.168
# auth password must be at least 32 characters
#auth: very-strong-password
#readonly: yes
replication:
binlog: yes
# Limit sync speed to *MB/s, -1: no limit
sync_speed: -1
slaveof:
# to identify a master even if it moved(ip, port changed)
# if set to empty or not defined, ip:port will be used.
id: svc_2
# sync|mirror, default is sync
type: mirror
host: 182.48.115.236
port: 8888
logger:
level: debug
output: log.txt
rotate:
size: 1000000000
leveldb:
# in MB
cache_size: 500
# in MB
write_buffer_size: 64
# in MB/s
compaction_speed: 1000
# yes|no
compression: yes
3)啟動服務(兩節點啟動命令一樣)
[root@master-node1 ~]# /home/slim/ssdb/ssdb-server -d /home/slim/ssdb/ssdb.conf
ssdb-server 1.9.4
Copyright (c) 2012-2015 ssdb.io
[root@master-node1 ~]# ps -ef|grep ssdb
root 23803 1 0 21:05 ? 00:00:00 /home/slim/ssdb/ssdb-server -d /home/slim/ssdb/ssdb.conf
root 23819 23719 0 21:05 pts/0 00:00:00 grep ssdb
.........................................................................................................
關閉命令:
/home/slim/ssdb/ssdb-server /home/slim/ssdb/ssdb.conf -s stop
幫忙命令
/home/slim/ssdb/ssdb-server -h
.........................................................................................................
4)數據同步測試
在master-node1節點上寫入數據
[root@master-node1 ~]# /home/slim/ssdb/ssdb-cli -h 182.48.115.236 -p 8888
ssdb (cli) - ssdb command line tool.
Copyright (c) 2012-2016 ssdb.io
'h' or 'help' for help, 'q' to quit.
ssdb-server 1.9.4
ssdb 182.48.115.236:8888> set name wangshibo
ok
(0.001 sec)
ssdb 182.48.115.236:8888> get name
wangshibo
(0.001 sec)
ssdb 182.48.115.236:8888>
在master-node2節點上查看:
[root@master-node2 ~]# /home/slim/ssdb/ssdb-cli -h 182.48.115.237 -p 8888
ssdb (cli) - ssdb command line tool.
Copyright (c) 2012-2016 ssdb.io
'h' or 'help' for help, 'q' to quit.
ssdb-server 1.9.4
ssdb 182.48.115.237:8888> get name
wangshibo
(0.001 sec)
同理,在master-node2節點上寫入數據
[root@master-node2 ~]# /home/slim/ssdb/ssdb-cli -h 182.48.115.237 -p 8888
ssdb (cli) - ssdb command line tool.
Copyright (c) 2012-2016 ssdb.io
'h' or 'help' for help, 'q' to quit.
ssdb-server 1.9.4
ssdb 182.48.115.237:8888> set huanqiutest hahahah
ok
(0.001 sec)
ssdb 182.48.115.237:8888>
然后在另一台master-node1節點上查看
[root@master-node1 ~]# /home/slim/ssdb/ssdb-cli -h 182.48.115.236 -p 8888
ssdb (cli) - ssdb command line tool.
Copyright (c) 2012-2016 ssdb.io
'h' or 'help' for help, 'q' to quit.
ssdb-server 1.9.4
ssdb 182.48.115.236:8888> get huanqiutest
hahahah
(0.001 sec)
以上說明ssdb主主同步環境已經實現!
..............................................................................
ssdb服務監控
info 命令返回的信息
[root@master-node1 ~]# /home/slim/ssdb/ssdb-cli -h 182.48.115.236 -p 8888
........
ssdb 182.48.115.236:8888> info
........
replication
client 182.48.115.237:56014
type : mirror
status : SYNC
last_seq : 3
replication
slaveof 182.48.115.237:8888
id : svc_1
type : mirror
status : SYNC
last_seq : 2
copy_count : 1
sync_count : 1
[root@master-node2 ~]# /home/slim/ssdb/ssdb-cli -h 182.48.115.237 -p 8888
.........
ssdb 182.48.115.237:8888> info
.........
replication
client 182.48.115.236:50210
type : mirror
status : SYNC
last_seq : 2
replication
slaveof 182.48.115.236:8888
id : svc_2
type : mirror
status : SYNC
last_seq : 3
copy_count : 1
sync_count : 0
............................................................................
info命令后的消息參數解釋:
1)binlogs
當前實例的寫操作狀態.
capacity: binlog 隊列的最大長度
min_seq: 當前隊列中的最小 binlog 序號
max_seq: 當前隊列中的最大 binlog 序號
2)replication
可以有多條 replication 記錄. 每一條表示一個連接進來的 slave(client), 或者一個當前服務器所連接的 master(slaveof).
slaveof|client ip:port, 遠端 master/slave 的 ip:port。
type: 類型, sync|mirror.
status: 當前同步狀態, DISCONNECTED|INIT|OUT_OF_SYNC|COPY|SYNC。
last_seq: 上一條發送或者收到的 binlog 的序號。
slaveof.id: master 的 id(這是從 slave's 角度來看的, 你永遠不需要在 master 上配置它自己的 id)。
slaveof.copy_count: 在全量同步時, 已經復制的 key 的數量。
slaveof.sync_count: 發送或者收到的 binlog 的數量。
3)關於 status:
DISCONNECTED: 與 master 斷開了連接, 一般是網絡中斷。
INIT: 初始化狀態。
OUT_OF_SYNC: 由於短時間內在 master 有大量寫操作, 導致 binlog 隊列淘汰, slave 丟失同步點, 只好重新復制全部的數據。
COPY: 正在復制基准數據的過程中, 新的寫操作可能無法及時地同步。
SYNC: 同步狀態是健康的.
4)判斷同步狀態
binlogs.max_seq 是指當前實例上的最新一次的寫(寫/更新/刪除)操作的序號, replication.client.last_seq 是指已發送給 slave 的最新一條 binlog 的序號。所以, 如果你想判斷主從同步是否已經同步到位(實時更新), 那么就判斷 binlogs.max_seq 和 replication.client.last_seq 是否相等。
---------------------SSDB備份與恢復----------------------
1)備份
支持了在線備份功能, 可以在不停止服務的情況下備份服務器數據,這個功能讓 SSDB 更加成為一個真正生產環境的存儲服務器。
[root@master-node1 ~]# /home/slim/ssdb/ssdb-dump 182.48.115.237 8888 ./backup_dir
這條命令從監聽在182.48.115.237:8888 的SSDB服務器上備份全量的數據, 保存到本地新創建的目錄 backup_dir, 這個目錄其實是一個 LevelDB 的數據庫(db)。
2)恢復
將 backup_dir 傳輸到服務器, 修改新ssdb服務器的配置文件, 將 SSDB 使用的數據庫名改為 backup_dir, 然后重啟 SSDB 即可。
3)使用主從(Master-Slave)架構實時備份
注意:
a)一般, 建議你將 logger.level 設置為 debug 級別。詳情參考:日志解讀
b)利用配置文件的 deny, allow 指令限制可信的來源 IP 訪問,提高服務的安全。
c)SSDB 的配置文件使用一個 TAB 來表示一級縮進, 不要使用空格來縮進, 無論你用2個, 3個, 4個, 或者無數個空格都不行!
d)一定要記得修改你的 Linux 內核參數, 關於 max open files(最大文件描述符數)的內容,詳情參考:構建C1000K的服務器
