啟動(dòng)一個(gè)centos容器
docker run -it centos7-python3.7:latest
安裝epel源
yum install epel-release
安裝redis
yum instal redis
安裝supervisor
yum install supervisor
修改redis配置文件
注釋這三行
因?yàn)槲覀円\(yùn)行多個(gè)redis,所以為了區(qū)分他們的存儲(chǔ)厉颤,把這個(gè)文件加上端口號(hào)命名
確認(rèn)supervisor的配置文件,這兩行要打開,才能去找配置的ini文件
設(shè)置supervisor啟動(dòng)redis的ini文件
[program:redis-6379] #這里是任務(wù)名
;執(zhí)行的命令
command=/root/virtualenv/cmdb/bin/uwsgi /cmdb/SharkAPAMP/conf/qf_uwsgi.ini
priority=999 ; 優(yōu)先級(jí)(越小越優(yōu)先)
autostart=true ; supervisord啟動(dòng)時(shí)孽惰,該程序也啟動(dòng)
autorestart=true ; 異常退出時(shí)轨淌,自動(dòng)啟動(dòng)
startsecs=10 ; 啟動(dòng)后持續(xù)10s后未發(fā)生異常,才表示啟動(dòng)成功
startretries=3 ; 異常后欲逃,自動(dòng)重啟次數(shù)
exitcodes=0,2 ; exit異常拋出的是0找蜜、2時(shí)才認(rèn)為是異常
stopsignal=QUIT ; 殺進(jìn)程的信號(hào)
; 在程序發(fā)送stopignal后,等待操作系統(tǒng)將SIGCHLD返回給supervisord的秒數(shù)稳析。
; 如果在supervisord從進(jìn)程接收到SIGCHLD之前經(jīng)過了這個(gè)秒數(shù)洗做,
; supervisord將嘗試用最終的SIGKILL殺死它
stopwaitsecs=1
user=root ; 設(shè)置啟動(dòng)該程序的用戶
log_stdout=true ; 如果為True弓叛,則記錄程序日志
log_stderr=false ; 如果為True,則記錄程序錯(cuò)誤日志
logfile=/var/log/qf_cmdb.log ; 程序日志路徑
logfile_maxbytes=1MB ; 日志文件最大大小
logfile_backups=10 ; 日志文件最大數(shù)量
用supervisor啟動(dòng)redis
supervisord -c /etc/supervisord.conf
supervisorctl 進(jìn)入supervisor的命令行 可以查看和管理supervisor的進(jìn)程
不進(jìn)入supervisor的命令行诚纸,也可以在外面執(zhí)行
RDB 保存的模式
save
和bgsave
重啟redis撰筷,看看我們?cè)O(shè)置的name還再不在
bgsave 命令和 save基本一樣,就是 bgsave 命令不會(huì)產(chǎn)生阻塞
127.0.0.1:6379> bgsave
Background saving started
127.0.0.1:6379>
也可以動(dòng)態(tài)地設(shè)置一些配置畦徘,不用重啟redis服務(wù)
AOF 保存的模式
Redis 目前支持三種 AOF 保存模式毕籽,它們分別是:
AOF_FSYNC_NO :不保存。
AOF_FSYNC_EVERYSEC :每一秒鐘保存一次井辆。(生產(chǎn)中一般選這種)
AOF_FSYNC_ALWAYS :每執(zhí)行一個(gè)命令保存一次
不保存
在這種模式下关筒, SAVE 只會(huì)在以下任意一種情況中被執(zhí)行:
Redis 被關(guān)閉
AOF 功能被關(guān)閉
系統(tǒng)的寫緩存被刷新(可能是緩存已經(jīng)被寫滿,或者定期保存操作被執(zhí)行)
這三種情況下的 SAVE 操作都會(huì)引起 Redis 主進(jìn)程阻塞杯缺。
每執(zhí)行一個(gè)命令保存一次
在這種模式下蒸播,每次執(zhí)行完一個(gè)命令之后, WRITE 和 SAVE 都會(huì)被執(zhí)行萍肆。
另外袍榆,因?yàn)?SAVE 是由 Redis 主進(jìn)程執(zhí)行的,所以在 SAVE 執(zhí)行期間塘揣,主進(jìn)程會(huì)被阻塞包雀,不能接受命令請(qǐng)求。
AOF 三種保存模式的比較
因?yàn)樽枞僮鲿?huì)讓 Redis 主進(jìn)程無法持續(xù)處理請(qǐng)求亲铡, 所以一般說來才写, 阻塞操作執(zhí)行得越少、完成得越快奴愉, Redis 的性能就越好琅摩。
模式 1 的保存操作只會(huì)在AOF 關(guān)閉或 Redis 關(guān)閉時(shí)執(zhí)行, 或者由操作系統(tǒng)觸發(fā)锭硼, 在一般情況下房资, 這種模式只需要為寫入阻塞, 因此它的寫入性能要比后面兩種模式要高檀头, 當(dāng)然轰异, 這種性能的提高是以降低安全性為代價(jià)的: 在這種模式下, 如果運(yùn)行的中途發(fā)生停機(jī)暑始, 那么丟失數(shù)據(jù)的數(shù)量由操作系統(tǒng)的緩存沖洗策略決定搭独。
模式 2 在性能方面要優(yōu)于模式 3 , 并且在通常情況下廊镜, 這種模式最多丟失不多于 2 秒的數(shù)據(jù)牙肝, 所以它的安全性要高于模式 1 , 這是一種兼顧性能和安全性的保存方案。
模式 3 的安全性是最高的配椭, 但性能也是最差的虫溜, 因?yàn)榉?wù)器必須阻塞直到命令信息被寫入并保存到磁盤之后, 才能繼續(xù)處理請(qǐng)求股缸。
綜合起來衡楞,三種 AOF 模式的操作特性可以總結(jié)如下:
模式 | WRITE 是否阻塞? | SAVE 是否阻塞敦姻? | 停機(jī)時(shí)丟失的數(shù)據(jù)量 |
---|---|---|---|
AOF_FSYNC_NO | 阻塞 | 阻塞 | 操作系統(tǒng)最后一次對(duì) AOF 文件觸發(fā) SAVE 操作之后的數(shù)據(jù)瘾境。 |
AOF_FSYNC_EVERYSEC | 阻塞 | 不阻塞 | 一般情況下不超過 2 秒鐘的數(shù)據(jù)。 |
AOF_FSYNC_ALWAYS | 阻塞 | 阻塞 | 最多只丟失一個(gè)命令的數(shù)據(jù)镰惦。 |
BGREWRITEAOF
AOF重寫機(jī)制
為什么需要重寫機(jī)制?
AOF 文件通過同步 Redis 服務(wù)器所執(zhí)行的命令迷守, 從而實(shí)現(xiàn)了數(shù)據(jù)庫(kù)狀態(tài)的記錄, 但是旺入, 這種同步方式會(huì)造成一個(gè)問題: 隨著運(yùn)行時(shí)間的流逝盒犹, AOF 文件會(huì)變得越來越大。
對(duì)同一個(gè)鍵的狀態(tài)的多次不同操作眨业,而最終得到一個(gè)結(jié)果。比如對(duì)列表的添加刪除元素沮协。被頻繁操作的鍵龄捡。比如累加
重新機(jī)制是如何實(shí)現(xiàn)的?
實(shí)際上, AOF 重寫并不需要對(duì)原有的 AOF 文件進(jìn)行任何寫入和讀取慷暂, 它針對(duì)的是數(shù)據(jù)庫(kù)中鍵的當(dāng)前值聘殖,也就是源數(shù)據(jù)從目前的內(nèi)存中獲取。
考慮這樣一個(gè)情況行瑞, 如果服務(wù)器對(duì)鍵 list 執(zhí)行了以下四條命令:
RPUSH list 1 2 3 4 // [1, 2, 3, 4]
RPOP list // [1, 2, 3]
LPOP list // [2, 3]
LPUSH list 1 // [1, 2, 3]
那么當(dāng)前列表鍵 list 在數(shù)據(jù)庫(kù)中的值就為 [1, 2, 3] 奸腺。
如果我們要保存這個(gè)列表的當(dāng)前狀態(tài), 并且盡量減少所使用的命令數(shù)
血久, 那么最簡(jiǎn)單的方式不是去 AOF 文件上分析前面執(zhí)行的四條命令突照, 而是直接讀取 list 鍵在數(shù)據(jù)庫(kù)的當(dāng)前值
, 然后用一條 RPUSH 1 2 3 命令來代替前面的四條命令氧吐。
除了列表之外讹蘑,集合、字符串筑舅、有序集座慰、哈希表等鍵也可以用類似的方法來保存狀態(tài)。
根據(jù)鍵的類型翠拣, 使用適當(dāng)?shù)膶懭朊顏碇噩F(xiàn)鍵的當(dāng)前值版仔, 這就是 AOF 重寫的實(shí)現(xiàn)原理。
基本的步驟-->
for 遍歷所有數(shù)據(jù)庫(kù):
if 如果數(shù)據(jù)庫(kù)為空:
那么跳過這個(gè)數(shù)據(jù)庫(kù)
else:
寫入 SELECT 命令,用于切換數(shù)據(jù)庫(kù)
for 選擇一個(gè)庫(kù)后蛮粮,遍歷這個(gè)庫(kù)的所有鍵
if 如果鍵帶有過期時(shí)間益缎,并且已經(jīng)過期,那么跳過這個(gè)鍵
if 根據(jù)數(shù)據(jù)的類型蝉揍,進(jìn)行相關(guān)操作链峭。
AOF 重寫的實(shí)現(xiàn)方式
方式 | 區(qū)別 |
---|---|
bgrewriteaof 命令 | 不需要重啟服務(wù),不便于統(tǒng)一管理 |
配置文件實(shí)現(xiàn) | 需要重啟服務(wù)又沾,便于進(jìn)行統(tǒng)一管理 |
配置文件實(shí)現(xiàn)
aof_current_size
和aof_base_size
可以通過命令info persistence
查看到
redis 重寫流程圖
對(duì)于上圖有四個(gè)關(guān)鍵點(diǎn)補(bǔ)充一下:
在重寫期間弊仪,由于主進(jìn)程依然在響應(yīng)命令,為了保證最終備份的完整性杖刷;因此它依然會(huì)寫入舊的AOF file中励饵,如果重寫失敗,能夠保證數(shù)據(jù)不丟失滑燃。當(dāng)然這個(gè)是可以通過配置來決定在重寫期間是否進(jìn)行主進(jìn)程普通的 AOF 操作役听。
為了把重寫期間響應(yīng)的寫入信息也寫入到新的文件中,因此也會(huì)為子進(jìn)程保留一個(gè)buf表窘,防止新寫的file丟失數(shù)據(jù)典予。
重寫是直接把當(dāng)前內(nèi)存的數(shù)據(jù)生成對(duì)應(yīng)命令,并不需要讀取老的AOF文件進(jìn)行分析乐严、命令合并瘤袖。
AOF文件直接采用的文本協(xié)議,主要是兼容性好昂验、追加方便捂敌、可讀性高可認(rèn)為修改修復(fù)。注意:無論是RDB還是AOF都是先寫入一個(gè)臨時(shí)文件既琴,然后通過 rename 完成文件的替換工作占婉。
配置示例
// 要想使用 AOF 的全部功能,需要設(shè)置為 yes
appendonly yes
// AOF 文件名甫恩,路徑才看之前的 `dir` 配置項(xiàng)
appendfilename "appendonly.aof"
// 平常普通的 AOF 的策略
appendfsync everysec
// 當(dāng)執(zhí)行 AOF 重寫時(shí)逆济,是否繼續(xù)執(zhí)行平常普通的 AOF 操作。
// 這里設(shè)置文件 yes , 表示不執(zhí)行
// 因?yàn)榧偃缁腔瑫r(shí)執(zhí)行纹腌,兩種操作都會(huì)對(duì)磁盤 I/O 進(jìn)行訪問,造成
// I/O 訪問量過大滞磺,產(chǎn)生性能衰減
no-appendfsync-on-rewrite yes
// AOF 文件容量的增長(zhǎng)率
auto-aof-rewrite-percentage 100
// AOF 文件的最低容量升薯,就是當(dāng)前文件的大小大于此值時(shí),就會(huì)進(jìn)行重寫击困。當(dāng)然這只是其中一個(gè)條件涎劈。
auto-aof-rewrite-min-size 64mb
添加鍵值對(duì)數(shù)據(jù)广凸,觀察 AOF 文件
這里在命令行中設(shè)置角寸,以便立刻生效
[root@s1 ~]# redis-cli
127.0.0.1:6379> config get appendonly
1) "appendonly"
2) "no"
127.0.0.1:6379> config set appendonly yes
OK
127.0.0.1:6379> config get appendonly
1) "appendonly"
2) "yes"
進(jìn)行簡(jiǎn)單的數(shù)據(jù)添加操作
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> set hello python
OK
127.0.0.1:6379> set hello redis
OK
127.0.0.1:6379> incr nums
(integer) 1
127.0.0.1:6379> incr nums
(integer) 2
127.0.0.1:6379> incr nums
(integer) 3
127.0.0.1:6379> incr nums
(integer) 4
127.0.0.1:6379> rpush li a
(integer) 1
127.0.0.1:6379> rpush li b
(integer) 2
127.0.0.1:6379> rpush li b
(integer) 3
127.0.0.1:6379> rpush li c
(integer) 4
127.0.0.1:6379> exit
查看 AOF 文件
[root@s1 ~]# head appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
$5
hello
主動(dòng)觸發(fā)
先備份一份目前的 AOF 文件
[root@s1 ~]# cp /appendonly.aof{,.bak}
執(zhí)行命令 bgrewriteaof
127.0.0.1:6379> config get appendonly
1) "appendonly"
2) "yes"
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started
最后對(duì)比兩個(gè)文件的內(nèi)容的不同之處疗杉。
RDB 和 AOF區(qū)別
如何抉擇
從服務(wù)器開啟 RDB
始終開啟 AOF
不要使用主機(jī)的全部?jī)?nèi)存
特點(diǎn)
RDB
把當(dāng)前內(nèi)存的數(shù)據(jù)的狀態(tài)就像是以快照的形式存儲(chǔ)到本地硬盤中窿撬,這個(gè)文件是二進(jìn)制的方式存儲(chǔ)的奕纫。
AOF
把寫的命令備份到一個(gè)文件中,文件以明文方式存儲(chǔ)