Linux下Redis主從複製以及SSDB主主複製環境部署記錄

散盡浮華發表於2016-07-19

 

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

相關文章