部署Redis4.x單機版及配置RDB和AOF持久化
阿新 • • 發佈:2019-01-11
一、環境及軟體
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