1. 程式人生 > >部署Redis4.x單機版及配置RDB和AOF持久化

部署Redis4.x單機版及配置RDB和AOF持久化

一、環境及軟體

OS   soft version
 CentOS 7.5   redis-4.0.12(目前是4.x最新)

二、下載及編譯Redis

[[email protected] ~]# wget http://download.redis.io/releases/redis-4.0.12.tar.gz 
[[email protected] ~]# tar xf redis-4.0.12.tar.gz -C /usr/local/
[[email protected]
~]# cd /usr/local/ [[email protected] local]# ln -sv redis-4.0.12/ redis [[email protected] local]# cd redis [[email protected] redis]#less README.md [[email protected] redis]#yum install tcl -y #安裝依賴,需要8.5及以上版本,如果yum沒有可以到官網去下載原始碼編譯安裝 官方地址:https://sourceforge.net/projects/tcl/files/Tcl/ [
[email protected]
redis]#make [[email protected] redis]#make test [[email protected] redis]#make install

三、Redis生產啟動方案(centos6)

如果一般的學習,那就隨便用redis-server啟動一下redis,做一些實驗,這樣的話,沒什麼意義
要把redis作為一個系統的daemon程序去執行的,每次系統啟動,redis程序一起啟動
(1)redis utils目錄下,有個redis_init_script指令碼
(2)將redis_init_script指令碼拷貝到linux的/etc/init.d目錄中,將redis_init_script重新命名為redis_6379,6379是我們希望這個redis例項監聽的埠號
(
3)修改redis_6379指令碼的第6行的REDISPORT,設定為相同的埠號(預設就是6379) (4)建立兩個目錄:/etc/redis(存放redis的配置檔案),/var/redis/6379(存放redis的持久化檔案) (5)修改redis配置檔案(預設在根目錄下,redis.conf),拷貝到/etc/redis目錄中,修改名稱為6379.conf (6)修改redis.conf中的部分配置為生產環境
bind 0.0.0.0 繫結的埠 daemonize yes 讓redis以daemon程序執行 pidfile
/var/run/redis_6379.pid 設定redis的pid檔案位置 port 6379 設定redis的監聽埠號 dir /var/redis/6379 設定持久化檔案的儲存位置,需要手動建立 (7)啟動redis,執行cd /etc/init.d, chmod 777 redis_6379,./redis_6379 start (8)確認redis程序是否啟動,ps -ef | grep redis (9)讓redis跟隨系統啟動自動啟動 在redis_6379指令碼中,最上面,加入兩行註釋 # chkconfig: 2345 90 10 # description: Redis is a persistent key-value database chkconfig redis_6379 on
centos7(其餘參照centos6,下面主要為Redis系統啟動指令碼)
[[email protected] system]# cd /usr/lib/systemd/system
[[email protected] system]# cat redis.service 
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target

[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /etc/redis/redis_6379.conf
ExecReload=/bin/kill -s HUP $MAINPID 
ExecStop=/bin/kill -s QUIT $MAINPID 
PIDFile=/var/run/redis_6379.pid
PrivateTmp=true

[Install]
WantedBy=multi-user.target

[[email protected] system]# systemctl enable redis
[[email protected] system]# systemctl start redis
redis-cli的簡單使用
redis-cli SHUTDOWN,連線本機的6379埠停止redis程序
redis-cli -h 127.0.0.1 -p 6379 SHUTDOWN,制定要連線的ip和埠號
redis-cli PING,ping redis的埠,看是否正常
redis-cli,進入互動式命令列
SET k1 v1
GET k1

 四、設定Redis RDB持久化及資料恢復

1.配置

RDB預設配置,具體含義看英文註解。如果滿足配置中的需求,那麼就生成一個新的dump.rdb檔案,就是當前redis記憶體中完整的資料快照,這個操作也被稱之為snapshotting,快照也可以手動呼叫save或者bgsave命令,同步或非同步執行rdb快照生成
save可以設定多個,就是多個snapshotting檢查點,每到一個檢查點,就會去check一下,是否有指定的key數量發生了變更,如果有,就生成一個新的dump.rdb檔案

2、RDB持久化機制的工作流程

1)redis根據配置自己嘗試去生成rdb快照檔案
(2)fork一個子程序出來
(3)子程序嘗試將資料dump到臨時的rdb快照檔案中
(4)完成rdb快照檔案的生成之後,就替換之前的舊的快照檔案

dump.rdb,每次生成一個新的快照,都會覆蓋之前的老快照

3、基於RDB持久化機制的資料恢復實驗

(1)在redis中儲存幾條資料,立即停掉redis程序,然後重啟redis,看看剛才插入的資料還在不在

[[email protected] ~]# redis-cli 
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> set k3 v3
OK
127.0.0.1:6379> exit
[[email protected] ~]# redis-cli SHUTDOWN      
[[email protected] ~]# redis-cli 
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
"v2"

#可以看到重啟後資料還在,這是因為通過redis-cli SHUTDOWN這種方式去停掉redis,其實是一種安全退出的模式,redis在退出的時候會將記憶體中的資料立即生成一份完整的rdb快照

(2)在redis中再儲存幾條新的資料,用kill -9粗暴殺死redis程序,模擬redis故障異常退出,導致記憶體資料丟失的場景

[[email protected] ~]# redis-cli SHUTDOWN
[[email protected] ~]# systemctl start redis
[[email protected] ~]# 
[[email protected] ~]# 
[[email protected] ~]# redis-cli 
127.0.0.1:6379> set k4 v4
OK
127.0.0.1:6379> set k5 v5
OK
127.0.0.1:6379> exit
[[email protected] ~]# kill -9 `ps aux|grep redis|grep -v grep|awk '{print $2}'`
[[email protected] ~]# ps aux|grep redis
root      12732  0.0  0.0 112664   972 pts/0    S+   22:30   0:00 grep --color=auto redis
[[email protected] ~]# systemctl start redis
[[email protected] ~]# ps aux|grep redis
root      12740  0.1  0.4 145260  7564 ?        Ssl  22:30   0:00 /usr/local/bin/redis-server 0.0.0.0:6379
root      12745  0.0  0.0 112664   972 pts/0    S+   22:30   0:00 grep --color=auto redis
[[email protected] ~]# redis-cli 
127.0.0.1:6379> get k4
(nil)
127.0.0.1:6379> get k5
(nil)

# 最後結果是redis程序異常被殺掉,幾條最新的資料就丟失了

五、AOF持久化的配置

1.AOF持久化配置

AOF持久化,預設是關閉的,預設是開啟RDB持久化

appendonly yes,可以開啟AOF持久化機制,在生產環境裡面,一般來說AOF都是要開啟的,除非你說隨便丟個幾分鐘的資料也無所謂

開啟AOF持久化機制之後,redis每次接收到一條寫命令,就會寫入日誌檔案中,當然是先寫入os cache的,然後每隔一定時間再fsync一下

而且即使AOF和RDB都開啟了,redis重啟的時候,也是優先通過AOF進行資料恢復的,因為aof資料比較完整

可以配置AOF的fsync策略,有三種策略可以選擇:
一種是每次寫入一條資料就執行一次fsync; 
  always: 每次寫入一條資料,立即將這個資料對應的寫日誌fsync到磁碟上去,效能非常非常差,吞吐量很低; 確保說redis裡的資料一條都不丟,那就只能這樣了
一種是每隔一秒執行一次fsync;   everysec: 每秒將os cache中的資料fsync到磁碟,這個最常用的,生產環境一般都這麼配置,效能很高,QPS還是可以上萬的
一種是不主動執行fsync
  no: 僅僅redis負責將資料寫入os cache就撒手不管了,然後後面os自己會時不時有自己的策略將資料刷入磁碟,不可控了

2、AOF持久化的資料恢復實驗

[[email protected] ~]# vim /etc/redis/redis_6379.conf 
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
[[email protected] ~]# systemctl stop redis
[[email protected] ~]# systemctl start redis
[[email protected] ~]# redis-cli 
127.0.0.1:6379> get k1  #為什麼現在k1的值沒有了?
(nil)
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
127.0.0.1:6379> exit
[[email protected] ~]# kill -9 `ps aux|grep redis|grep -v grep|awk '{print $2}'`
[[email protected] ~]# systemctl start redis
[[email protected] ~]# redis-cli 
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
"v2"

#kill -9殺掉redis程序,重新啟動redis程序,發現數據被恢復回來了,就是從AOF檔案中恢復回來的
#redis程序啟動的時候,直接就會從appendonly.aof中載入所有的日誌,把記憶體中的資料恢復回來
#在有rdb的dump和aof的appendonly的同時,rdb裡也有部分資料,aof裡也有部分資料,這個時候其實會發現,rdb的資料不會恢復到記憶體中

3、AOF rewrite

redis中的資料其實有限的,很多資料可能會自動過期,可能會被使用者刪除,可能會被redis用快取清除的演算法清理掉

redis中的資料會不斷淘汰掉舊的,就一部分常用的資料會被自動保留在redis記憶體中

所以可能很多之前的已經被清理掉的資料,對應的寫日誌還停留在AOF中,AOF日誌檔案就一個,會不斷的膨脹,到很大很大

所以AOF會自動在後臺每隔一定時間做rewrite操作,比如日誌裡已經存放了針對100w資料的寫日誌了; redis記憶體只剩下10萬; 基於記憶體中當前的10萬資料構建一套最新的日誌,到AOF中; 覆蓋之前的老日誌; 確保AOF日誌檔案不會過大,保持跟redis記憶體資料量一致

redis 2.4之前,還需要手動,開發一些指令碼,crontab,通過BGREWRITEAOF命令去執行AOF rewrite,但是redis 2.4之後,會自動進行rewrite操作

在redis.conf中,可以配置rewrite策略

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

比如說上一次AOF rewrite之後,是128mb

然後就會接著128mb繼續寫AOF的日誌,如果發現增長的比例,超過了之前的100%,256mb,就可能會去觸發一次rewrite

但是此時還要去跟min-size,64mb去比較,256mb > 64mb,才會去觸發rewrite

(1)redis fork一個子程序
(2)子程序基於當前記憶體中的資料,構建日誌,開始往一個新的臨時的AOF檔案中寫入日誌
(3)redis主程序,接收到client新的寫操作之後,在記憶體中寫入日誌,同時新的日誌也繼續寫入舊的AOF檔案
(4)子程序寫完新的日誌檔案之後,redis主程序將記憶體中的新日誌再次追加到新的AOF檔案中
(5)用新的日誌檔案替換掉舊的日誌檔案

4、AOF破損檔案的修復

如果redis在append資料到AOF檔案時,機器宕機了,可能會導致AOF檔案破損

用redis-check-aof --fix命令來修復破損的AOF檔案

 [[email protected] ~]# redis-check-aof --fix /var/redis/appendonly.aof
 AOF analyzed: size=81, ok_up_to=81, diff=0
 AOF is valid

5、AOF和RDB同時工作

1)如果RDB在執行snapshotting操作,那麼redis不會執行AOF rewrite; 如果redis再執行AOF rewrite,那麼就不會執行RDB snapshotting
(2)如果RDB在執行snapshotting,此時使用者執行BGREWRITEAOF命令,那麼等RDB快照生成之後,才會去執行AOF rewrite
(3)同時有RDB snapshot檔案和AOF日誌檔案,那麼redis重啟的時候,會優先使用AOF進行資料恢復,因為其中的日誌更完整

六、企業級的資料備份方案

1.備份方案

RDB非常適合做冷備,每次生成之後,就不會再有修改了
資料備份方案
(1)寫crontab定時排程指令碼去做資料備份
(2)每小時都copy一份rdb的備份,到一個目錄中去,僅僅保留最近48小時的備份
(3)每天都保留一份當日的rdb的備份,到一個目錄中去,僅僅保留最近1個月的備份
(4)每次copy備份的時候,都把太舊的備份給刪了
(5)每天晚上將當前伺服器上所有的資料備份,傳送一份到遠端的雲服務上去

2.資料恢復方案

1)如果是redis程序掛掉,那麼重啟redis程序即可,直接基於AOF日誌檔案恢復資料,不演示了,在AOF資料恢復那一塊,演示了,fsync everysec,最多就丟一秒的數
(2)如果是redis程序所在機器掛掉,那麼重啟機器後,嘗試重啟redis程序,嘗試直接基於AOF日誌檔案進行資料恢復,AOF沒有破損,也是可以直接基於AOF恢復的,AOF append-only,順序寫入,如果AOF檔案破損,那麼用redis-check-aof fix
(3)如果redis當前最新的AOF和RDB檔案出現了丟失/損壞,那麼可以嘗試基於該機器上當前的某個最新的RDB資料副本進行資料恢復,當前最新的AOF和RDB檔案都出現了丟失/損壞到無法恢復,找到RDB最新的一份備份,小時級的備份可以了,小時級的肯定是最新的,copy到redis裡面去,就可以恢復到某一個小時的資料

3.資料恢復的坑

appendonly.aof + dump.rdb,優先用appendonly.aof去恢復資料,但是我們發現redis自動生成的appendonly.aof是沒有資料的

然後我們自己的dump.rdb是有資料的,但是明顯沒用我們的資料

redis啟動的時候,自動重新基於記憶體的資料,生成了一份最新的rdb快照,直接用空的資料,覆蓋掉了我們有資料的,拷貝過去的那份dump.rdb

你停止redis之後,其實應該先刪除appendonly.aof,然後將我們的dump.rdb拷貝過去,然後再重啟redis

很簡單,就是雖然你刪除了appendonly.aof,但是因為打開了aof持久化,redis就一定會優先基於aof去恢復,即使檔案不在,那就建立一個新的空的aof檔案

停止redis,暫時在配置中關閉aof,然後拷貝一份rdb過來,再重啟redis,資料能不能恢復過來,可以恢復過來

腦子一熱,再關掉redis,手動修改配置檔案,開啟aof,再重啟redis,資料又沒了,空的aof檔案,所有資料又沒了

在資料安全丟失的情況下,基於rdb冷備,如何完美的恢復資料,同時還保持aof和rdb的雙開

停止redis,關閉aof,拷貝rdb備份,重啟redis,確認資料恢復,直接在命令列熱修改redis配置,開啟aof,這個redis就會將記憶體中的資料對應的日誌,寫入aof檔案中

此時aof和rdb兩份資料檔案的資料就同步了,同步後關閉Redis,修改配置檔案開啟aof,再啟動Redis就OK了

熱修改命令

[[email protected] ~]# redis-cli 
127.0.0.1:6379> CONFIG GET appendonly
1) "appendonly"
2) "no"
127.0.0.1:6379> CONFIG SET appendonly yes