1. 程式人生 > 實用技巧 >0121. Best Time to Buy and Sell Stock (E)

0121. Best Time to Buy and Sell Stock (E)

redis主從複製

1 在開啟主從賦值的時候,使用的是RDB的方式同步主從資料的
2 同步開始之後,通過主庫命令傳播的方式,主動複製的方式實現
3 2.8版本以後實現了psync的機制實現斷線重連

使用非同步複製。
一個主伺服器可以有多個從伺服器。
從伺服器也可以有自己的從伺服器。
複製功能不會阻塞主伺服器。
可以通過複製功能來讓主伺服器免於執行持久化操作,由從伺服器去執行持久化操作即可。

redis主從複製原理

1. 從伺服器向主伺服器傳送 SYNC 命令。
2. 接到 SYNC 命令的主伺服器會呼叫BGSAVE 命令,建立一個 RDB 檔案,並使用緩衝區記錄接下來執行的所有寫命令。也就是儲存快照,然後記錄到快取,從庫不需要請求,只需要接收就可以了。
3. 當主伺服器執行完 BGSAVE 命令時,它會向從伺服器傳送 RDB 檔案,而從伺服器則會接收並載入這個檔案。
4. 主伺服器將緩衝區儲存的所有寫命令傳送給從伺服器執行。
從伺服器每秒一次的頻率,ping 主伺服器一次,並報告複製流的處理情況
主伺服器會記錄各個從伺服器最後一次向他傳送ping的時間
使用者可以通過配置,指定網路延遲的最大值 min-slaves-max-lag
以及執行寫操作所需的至少從伺服器數量 min-slaves-to-write
如果至少有min-slaves-to-write個伺服器,並且這些伺服器延遲值都少於min-slaves-max-lag秒
那麼主伺服器就會執行客戶端的寫操作

redis主從會有一個斷線重連的機制,當主從斷開後,主會保留沒有傳送的資料,當從伺服器好了他會將沒有傳輸的資料傳輸過去。
主伺服器只在有至少 N 個從伺服器的情況下,才執行寫操作
	從 Redis 2.8 開始, 為了保證資料的安全性, 可以通過配置, 讓主伺服器只在有至少 N 個當前已連線從伺服器的情況下, 才執行寫命令。
	不過, 因為 Redis 使用非同步複製, 所以主伺服器傳送的寫資料並不一定會被從伺服器接收到, 因此, 資料丟失的可能性仍然是存在的。
通過以下兩個引數保證資料的安全:
min-slaves-to-write <number of slaves>  #至少有 N 臺從庫與主庫完成同步了則認為主從同步成功
min-slaves-max-lag <number of seconds>  #網路延時的最大值,如果大於這個值,認為不成功的

redis主從複製配置[一主兩從]

注意: redis沒有做資料持久化的時候不要做主從複製,因為一旦主庫宕機了,資料都沒了,然後通過主從複製將從庫資料也重寫了,這樣會導致重大事故

環境:

主節點:6380
從節點:6381 6382

mkdir /nosql/638{0..2}
vim   /nosql/6380/redis.conf
port 6380
daemonize yes
pidfile /nosql/6380/redis.pid
loglevel notice
logfile "/nosql/6380/redis.log"
dbfilename dump.rdb
dir /nosql/6380
protected-mode no


vim   /nosql/6381/redis.conf
port 6381
daemonize yes
pidfile /nosql/6381/redis.pid
loglevel notice
logfile "/nosql/6381/redis.log"
dbfilename dump.rdb
dir /nosql/6381
protected-mode no


vim   /nosql/6382/redis.conf
port 6382
daemonize yes
pidfile /nosql/6382/redis.pid
loglevel notice
logfile "/nosql/6382/redis.log"
dbfilename dump.rdb
dir /nosql/6382
protected-mode no

啟動:
redis-server /nosql/6380/redis.conf
redis-server /nosql/6381/redis.conf
redis-server /nosql/6382/redis.conf

檢查:
[root@k8s-master1 redis]# ps -ef|grep redis
root      54840      1  0 19:34 ?        00:00:00 redis-server *:6380
root      54844      1  0 19:34 ?        00:00:00 redis-server *:6381
root      54848      1  0 19:34 ?        00:00:00 redis-server *:6382

開啟主從

6381/6382命令列:
[root@k8s-master1 redis]# redis-cli -p 6381
127.0.0.1:6381> SLAVEOF 127.0.0.1 6380     #從哪個機器哪個埠進行復制
OK
127.0.0.1:6381> exit
[root@k8s-master1 redis]# redis-cli -p 6382
127.0.0.1:6382> SLAVEOF 127.0.0.1 6380     #從哪個機器哪個埠進行復制
OK
127.0.0.1:6382> exit



#查詢主從狀態:
主狀態:
[root@k8s-master1 redis]# redis-cli -p 6380
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:2    #可以看到從庫數量 下面可以看到從庫相應狀態資訊
slave0:ip=127.0.0.1,port=6381,state=online,offset=169,lag=1
slave1:ip=127.0.0.1,port=6382,state=online,offset=169,lag=1
master_repl_offset:169
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:168



從狀態:
[root@k8s-master1 redis]# redis-cli -p 6381
127.0.0.1:6381> INFO replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_repl_offset:113
slave_priority:100
slave_read_only:1     #從庫預設不可以被寫入操作
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6381> exit
------------------------------------------------------------------------
[root@k8s-master1 redis]# redis-cli -p 6382
127.0.0.1:6382> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:141
slave_priority:100
slave_read_only:1      #從庫預設不可以被寫入操作
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6382> exit

測試主庫down了從庫替換

#主動停止主庫
[root@k8s-master1 redis]# redis-cli -p 6380
127.0.0.1:6380> shutdown
not connected> exit


#檢查從庫狀態
[root@k8s-master1 redis]# redis-cli -p 6381
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:down          #可以檢測到master主庫down了
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:701
master_link_down_since_seconds:35
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0


現在需要用 6381從庫來替代6380主庫,配置如下:
[root@k8s-master1 redis]# redis-cli -p 6381    #選擇一個從庫連線
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:701
master_link_down_since_seconds:35
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

切換為主庫:
127.0.0.1:6381> SLAVEOF no one
OK

從6382檢視狀態:
[root@k8s-master1 redis]# redis-cli -p 6382
127.0.0.1:6382> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:701
master_link_down_since_seconds:307
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

可以看到它還在連6380,現在需要把他改為連線到新的主庫 6381:
127.0.0.1:6382> SLAVEOF no one
OK
127.0.0.1:6382> SLAVEOF 127.0.0.1 6381
OK

redis 哨兵模式

將原有實驗切換回來:
[root@k8s-master1 redis]# redis-server /nosql/6381/redis.conf
[root@k8s-master1 redis]# redis-cli -p 6381
127.0.0.1:6381> SLAVEOF 127.0.0.1 6380
OK
127.0.0.1:6381> exit
[root@k8s-master1 redis]# redis-server /nosql/6382/redis.conf
[root@k8s-master1 redis]# redis-cli -p 6382
127.0.0.1:6382> SLAVEOF 127.0.0.1 6380
OK
127.0.0.1:6382> exit

主庫:
[root@k8s-master1 redis]# redis-cli -p 6380
127.0.0.1:6380> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=127,lag=0
slave1:ip=127.0.0.1,port=6382,state=online,offset=127,lag=0
master_repl_offset:127
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:126

問題:在監控到一個主庫出現問題時我們都是自己來通過命令切換,那有沒有不需要人工干預
自動切換呢? 接下來了解以下 哨兵模式 它就是解決這個問題的。

sentinel搭建

mkdir /nosql/26380
cd /nosql/26380
vim sentinel.conf 新增以下內容,儲存退出
#------------------------------------------
port 26380
dir "/nosql/26380"
sentinel monitor mymaster 127.0.0.1 6380 1
sentinel down-after-milliseconds mymaster 5000
#------------------------------------------

啟動:
redis-sentinel /nosql/26380/sentinel.conf &

啟動成功提醒:
67226:X 18 Sep 20:29:09.262 # Sentinel ID is 19c19134085099bf08c1d498e050fd51cc651de9
67226:X 18 Sep 20:29:09.262 # +monitor master mymaster 127.0.0.1 6380 quorum 1
67226:X 18 Sep 20:29:09.262 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:29:09.264 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:29:11.135 * +sentinel sentinel 8dce82a8f5e8b64c7f7d506c62a4d608d692a587 127.0.0.1 26379 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:29:11.140 # +new-epoch 2
66500:X 18 Sep 20:29:11.275 * +sentinel sentinel 19c19134085099bf08c1d498e050fd51cc651de9 127.0.0.1 26380 @ mymaster 127.0.0.1 6380

停止主庫測試:
[root@k8s-master1 26380]# redis-cli  -p 6380
127.0.0.1:6380> shutdown
not connected> exit



提示資訊:
[root@k8s-master1 26380]# redis-cli  -p 6380
127.0.0.1:6380> shutdown
not connected> exit
[root@k8s-master1 26380]# 67226:X 18 Sep 20:31:04.775 # +sdown master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.775 # +odown master mymaster 127.0.0.1 6380 #quorum 1/1
67226:X 18 Sep 20:31:04.775 # +new-epoch 3
67226:X 18 Sep 20:31:04.775 # +try-failover master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.776 # +vote-for-leader 19c19134085099bf08c1d498e050fd51cc651de9 3
66500:X 18 Sep 20:31:04.778 # +new-epoch 3
66500:X 18 Sep 20:31:04.778 # +vote-for-leader 19c19134085099bf08c1d498e050fd51cc651de9 3
67226:X 18 Sep 20:31:04.779 # 8dce82a8f5e8b64c7f7d506c62a4d608d692a587 voted for 19c19134085099bf08c1d498e050fd51cc651de9 3
66500:X 18 Sep 20:31:04.802 # +sdown master mymaster 127.0.0.1 6380
66500:X 18 Sep 20:31:04.802 # +odown master mymaster 127.0.0.1 6380 #quorum 1/1
66500:X 18 Sep 20:31:04.802 # Next failover delay: I will not start a failover before Fri Sep 18 20:37:05 2020
67226:X 18 Sep 20:31:04.852 # +elected-leader master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.852 # +failover-state-select-slave master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.915 # +selected-slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.915 * +failover-state-send-slaveof-noone slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:04.970 * +failover-state-wait-promotion slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:05.798 # +promoted-slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:05.798 # +failover-state-reconf-slaves master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:05.859 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
66500:X 18 Sep 20:31:05.860 # +config-update-from sentinel 19c19134085099bf08c1d498e050fd51cc651de9 127.0.0.1 26380 @ mymaster 127.0.0.1 6380
66500:X 18 Sep 20:31:05.860 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6382
66500:X 18 Sep 20:31:05.860 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6382
66500:X 18 Sep 20:31:05.860 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
67226:X 18 Sep 20:31:06.812 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:06.812 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:06.868 # +failover-end master mymaster 127.0.0.1 6380
67226:X 18 Sep 20:31:06.868 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6382
67226:X 18 Sep 20:31:06.868 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6382
67226:X 18 Sep 20:31:06.868 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
66500:X 18 Sep 20:31:10.898 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
67226:X 18 Sep 20:31:11.895 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382


可以看到master切換為了 127.0.0.1 6382	
[root@k8s-master1 26380]# redis-cli -p 6382
127.0.0.1:6382> info replication
# Replication
role:master      <------------- 6382成了主
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=30950,lag=0
master_repl_offset:31216
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:31215



重新啟動6380
[root@k8s-master1 26380]# redis-server /nosql/6380/redis.conf
提示:
67226:X 18 Sep 20:36:45.117 # -sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
66500:X 18 Sep 20:36:45.165 # -sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382
67226:X 18 Sep 20:36:55.047 * +convert-to-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6382

檢視資訊:
[root@k8s-master1 26380]# redis-cli -p 6382
127.0.0.1:6382> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=65917,lag=1    # 
slave1:ip=127.0.0.1,port=6380,state=online,offset=65917,lag=1    # 發現失聯的伺服器又重新加入到叢集了。
master_repl_offset:65917
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:65916

Sentinel管理命令:

redis-cli -p 26380 連線

PING :返回 PONG
SENTINEL masters :列出所有被監視的主伺服器
SENTINEL slaves <master name> 
SENTINEL get-master-addr-by-name <master name> : 返回給定名字的主伺服器的 IP 地址和埠號。 
SENTINEL reset <pattern> : 重置所有名字和給定模式 pattern 相匹配的主伺服器。 
SENTINEL failover <master name> : 當主伺服器失效時, 在不詢問其他 Sentinel 意見的情況下, 強制開始一次自動故障遷移。