當創建主從關係時,slave配置slaveof <master_host> <master_port> 。slave服務器會向主服務器發送一個sync命令。master接受並fork一個進程來執行BGSAVE命令。該命令生成一個RDB文件而且全量發送給slave服務器,slave服務器接收並載入RDB文件,同時,主服務器將緩衝區的命令以增量的方式發送給從服務器,最終使從服務器的數據狀態和主服務器保持一致。redis
當redis生成dump.rdb文件時,工做過程以下bash
redis主進程fork一個子進程服務器
fork出來的子進程將內存的數據集dump到臨時的RDB中session
當子進程對臨時的RDB文件寫入完畢,redis用新的RDB文件代替舊的RDB文件app
AOF :append only file。每當Redis執行一個改變數據集的命令時,這個命令都會被追加到AOF文件的末尾。當redis從新啓動時,程序能夠經過AOF文件恢復數據異步
Redis 監控最直接的方法固然就是使用系統提供的 info 命令來作了,只須要執行下面一條命令,就能得到 Redis 系統的狀態報告。分佈式
redis-cli info
其中跟RDB文件狀態監控相關的參數工具
rdb_changes_since_last_save 代表上次RDB保存之後改變的key次數性能
rdb_bgsave_in_progress 表示當前是否在進行bgsave操做。是爲1測試
rdb_last_save_time 上次保存RDB文件的時間戳
rdb_last_bgsave_time_sec 上次保存的耗時
rdb_last_bgsave_status 上次保存的狀態
rdb_current_bgsave_time_sec 目前保存RDB文件已花費的時間
其中跟AOF文件狀態監控相關的參數
aof_enabled AOF文件是否啓用
aof_rewrite_in_progress 表示當前是否在進行寫入AOF文件操做
aof_rewrite_scheduled
aof_last_rewrite_time_sec 上次寫入的時間戳
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok 上次寫入狀態
aof_last_write_status:ok 上次寫入狀態
在咱們優化master以前,能夠看看目前咱們的其中一個生產環境的的redis的持久化狀態
# Persistence loading:0 rdb_changes_since_last_save:116200 rdb_bgsave_in_progress:1 rdb_last_save_time:1448944451 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:85 rdb_current_bgsave_time_sec:33 aof_enabled:0 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:-1 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok
經過redis-cli的info命令,能夠看到 「rdb_last_bgsave_time_sec」參數的值,
這個值表示上次bgsave命令執行的時間。在磁盤IO定量的狀況下,redis佔用的內存越大,
這個值也就越大。一般「rdb_last_bgsave_time_sec」這個時間取決於兩個因素:
REDIS佔用的內存大小
磁盤的寫速度。
rdb_last_bgsave_time_sec:85
這個標識表示咱們上次保存dump RDB文件的時間。這個耗時受限於上面提到的兩個因素。
當redis處於 rdb_bgsave_in_progress狀態時,經過vmstat命令查看性能,獲得wa值偏高,也就是說CPU在等待
IO的請求完成,咱們線上的一個應用redis佔用的內存是5G左右,也就是redis會生成大約5G左右的dump.rdb文件
vmstat命令
r b swpd free buff cache si so bi bo in cs us sy id wa st 0 4 0 223912 2242680 5722008 0 0 200 48648 3640 5443 1 1 63 35 0 0 3 0 222796 2242680 5722052 0 0 16 48272 2417 5019 1 1 63 35 0 0 3 0 222300 2242680 5722092 0 0 40 24612 3042 3568 1 1 63 35 0 0 3 0 220068 2242680 5722124 0 0 64 40328 4304 4737 2 1 63 34 0 0 3 0 218952 2242680 5722216 0 0 100 48648 4966 5786 1 2 63 35 0 0 3 0 215356 2242680 5722256 0 0 0 66168 3546 4382 2 1 62 35 0
經過上面的輸出,看到BGSAVE 對於IO的性能影響比較大
那麼該如何解決由RDB文件帶來的性能上不足的問題,又能保證數據持久化的目的
一般的設計思路就是利用「Replication」機制來解決:即master不開啓RDB日誌和AOF日誌,來保證master的讀寫性能。而slave則開啓rdb和aof來進行持久化,保證數據的持久性,
我在測試機器上,開啓兩個實例,端口分別爲6379和6380
master: 172.16.76.232 6379 slave: 172.16.76.232 6380
修改master的redis.conf
關閉RDB
# save 900 1 # save 300 10 # save 60 10000
關閉AOF
appendonly no
分別啓動master和slave的redis
service redis start
修改slave配置,指向master服務器
redis-cli > slaveof 172.16.76.232 6379
查看slave的複製狀態
redis-cli > info replication
#!/bin/bash ID=1 while(($ID<50001)) do redis-cli set "my:$ID" "aaa_okthisis_Omb5EVIwBgPHgbRj64raygpeRLKaNhyB9sLF_$ID" redis-cli set "your:$ID" "your_okthisis_Omb5EVIwBgPHgbRj64raygpeRLKaNhyB9sLF_$ID" redis-cli set "her:$ID" "her_okthisis_Omb5EVIwBgPHgbRj64raygpeRLKaNhyB9sLF_$ID" redis-cli set "his:$ID" "his_okthisis_Omb5EVIwBgPHgbRj64raygpeRLKaNhyB9sLF_$ID" ID=$(($ID+1)) done
master redis > killall -9 redis-server
SLAVE redis > SLAVEOF NO ONE
取消Slave的同步,避免主庫在未完成數據恢復前就重啓,進而直接覆蓋掉從庫上的數據,致使全部的數據丟失。
cp /data/redis_data_slave/dump.rdb /data/redis_data/ cp /data/redis_data_slave/Append.AOF /data/redis_data/
master redis > dbsize
查看數據是否恢復
slave redis > slaveof 172.16.76.232 6379
背景介紹:
咱們的一臺redis服務器,硬件配置爲4核,4G內存。redis持久話方案是RDB。前面幾個月redis使用的
內存在1G左右。在一次重啓以後,redis只恢復了部分數據,這時查看redis.log文件。看見了以下的錯誤
[23635] 25 Jul 08:30:54.059 * 10000 changes in 60 seconds. Saving... [23635] 25 Jul 08:30:54.059 # Can't save in background: fork: Cannot allocate memory
這時,想起了redis啓動時的警告
WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
翻譯
警告:過量使用內存設置爲0!在低內存環境下,後臺保存可能失敗。爲了修正這個問題, 請在/etc/sysctl.conf 添加一項 'vm.overcommit_memory = 1' , 而後重啓(或者運行命令'sysctl vm.overcommit_memory=1' )使其生效。
vm.overcommit_memory不一樣的值說明
0 表示檢查是否有足夠的內存可用,若是是,容許分配;若是內存不夠,拒絕該請求,並返回一個錯誤給應用程序。
1 容許分配超出物理內存加上交換內存的請求
2 內核老是返回true
redis的數據回寫機制分爲兩種
同步回寫即SAVE命令。redis主進程直接寫數據到磁盤。當數據量大時,這個命令將阻塞,響應時間長
異步回寫即BGSAVE命令。redis 主進程fork一個子進程,複製主進程的內存並經過子進程回寫數據到磁盤。
因爲RDB文件寫的時候fork一個子進程。至關於複製了一個內存鏡像。當時系統的內存是4G,而redis佔用了
近3G的內存,所以確定會報內存沒法分配。若是 「vm.overcommit_memory」設置爲0,在可用內存不足的狀況
下,就沒法分配新的內存。若是 「vm.overcommit_memory」設置爲1。 那麼redis將使用交換內存。
解決辦法:
方法一: 修改內核參數 vi /etc/sysctl。設置 vm.overcommit_memory = 1
而後執行
``` sysctl -p ```
方法二: 使用交換內存並非一個完美的方案。最好的辦法是擴大物理內存。
使用slaveof命令後,長時間看不到數據同步。覺得複製功能失效,或配置錯了。其實,不用擔憂,有兩種方法能夠肯定是否正在創建複製。
在建立Redis複製時,一開始可能會發現Slave長時間不開始同步數據,可能數據量太大,致使了Master正在dump數據慢,此時若是你在Master上執行「top -p $(pgrep -d, redis-server)」命令,就能看到dump的過程
方式一: 經過「top」命令
[root@img1_u ~]# top -p $(pgrep -d, redis-server) top - 14:06:24 up 54 days, 6:13, 1 user, load average: 1.18, 1.32, 1.20 Tasks: 2 total, 1 running, 1 sleeping, 0 stopped, 0 zombie Cpu(s): 15.2%us, 1.7%sy, 0.6%ni, 81.9%id, 0.2%wa, 0.0%hi, 0.4%si, 0.0%st Mem: 24542176k total, 22771848k used, 1770328k free, 2245720k buffers Swap: 524280k total, 0k used, 524280k free, 4369452k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 21619 root 20 0 5654m 5.4g 388 R 99.9 23.0 0:23.70 redis-server 1663 root 20 0 5654m 5.4g 1068 S 15.3 23.0 5042:31 redis-server
redis-server是單進程的,如今經過「top」命令查看已經有2個進程,由於以前提到的,redis在創建複製的時,會在
主服務器上執行 BGSAVE 命令。fork一個子進程,dump出RDB文件。 master dump 完畢,而後再將快照文件傳給slave。
方式二:經過「rdb_bgsave_in_progress」標識
進入master的redis-cli
redis-cli > info persistence ... loading:0 rdb_changes_since_last_save:0 rdb_bgsave_in_progress:1 rdb_last_save_time:1448992510 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:4 rdb_current_bgsave_time_sec:1 ...
若是「rdb_bgsave_in_progress」爲1,那麼master正在進行bgsave命令。同時「rdb_current_bgsave_time_sec」
顯示bgsave命令已經執行的時間。因爲在master服務器上默認不開啓RDB和AOF日誌,若是「rdb_bgsave_in_progress」爲1,那麼就能夠確定因爲複製緣由發送一個「bgsave」指令 dump 出 RDB 文件。
有運營的同事反應,系統在登陸的狀況下,操做時會平白無故跳到登陸頁面。 因爲咱們的系統作了分佈式的
session,默認把session放到redis裏,按照以往的故障經驗。多是redis使用了最大內存上限
致使了沒法設置key。 登陸 redis 服務器查看 redis.conf 文件設置了最大8G內存「maxmemory 8G」
而後經過「redis-cli info memory 」 查詢到目前的內存使用狀況 「used_memory_human:7.71G」
接着經過redis-cli工具設置值 。報錯 「OOM command not allowed when used memory 」。再次
驗證了redis服務器已經達到了最大內存
解決方法:
關閉redis 服務器 redis-cli shutdown
修改配置文件的最大內存 「maxmemory」
啓動redis服務器 redis-server redis.conf