前面的文章已經介紹了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的伺服器