
一、RDB持久化模式缺陷
1、問(wèn)題描述:
并發(fā)200路,模擬不斷寫(xiě)Redis,持續(xù)4小時(shí)后,接口調(diào)用開(kāi)始出現(xiàn)大量失敗,錯(cuò)誤信息如下:
{"data":{"sendResult":null},"base":{"returncode":"99999","returndesc":"系統(tǒng)異常:MISCONF?Redis?is?configured?to?save?RDB?snapshots,?but?is?currently?not?able?to?persist?on?disk.?Commands?that?may?modify?the?data?set?are?disabled.?Please?check?Redis?logs?for?details?about?the?error."},"qrybase":{"total":0,"count":0,"start":0}}
2、原因分析:
解讀錯(cuò)誤信息,以為是磁盤(pán)不夠用引起,結(jié)果發(fā)現(xiàn)磁盤(pán)還剩余42%,如下所示:

于是根據(jù)錯(cuò)誤信息提示開(kāi)啟Redis日志,繼續(xù)壓測(cè),接口依然報(bào)錯(cuò),但可從Redis日志信息中
Can’t save in background: fork: Cannot allocate memory
進(jìn)程使用內(nèi)存不當(dāng)有關(guān),查看Redis主進(jìn)程占用內(nèi)存如下:占用近55%*4G內(nèi)存

具體原因:Redis在保存數(shù)據(jù)到硬盤(pán)時(shí)為了避免主進(jìn)程假死,需要Fork一份主進(jìn)程,然后在Fork進(jìn)程內(nèi)完成數(shù)據(jù)保存到硬盤(pán)的操作,如果主進(jìn)程使用了2.2GB的內(nèi)存,F(xiàn)ork子進(jìn)程的時(shí)候需要額外的2.2GB,此時(shí)內(nèi)存就不夠了,F(xiàn)ork失敗,進(jìn)而數(shù)據(jù)保存硬盤(pán)也失敗了。
3、緩解方案(不能根本解決問(wèn)題):
3.1 修改redis.conf文件中配置項(xiàng)stop-writes-on-bgsave-error no (默認(rèn)值為yes),即當(dāng)bgsave快照操作出錯(cuò)時(shí)停止寫(xiě)數(shù)據(jù)到磁盤(pán),這樣后面寫(xiě)錯(cuò)做均會(huì)失敗,為了不影響后續(xù)寫(xiě)操作,故需將該項(xiàng)值改為no
3.2 修改內(nèi)核參數(shù)(如下3種方式),但需要root權(quán)限:
(1)編輯/etc/sysctl.conf?,改vm.overcommit_memory=1,然后sysctl?-p?使配置文件生效
(2)sysctl?vm.overcommit_memory=1
(3)echo?1?>?/proc/sys/vm/overcommit_memory
二、AOF持久化模式缺陷
1、問(wèn)題1描述:
Redis主從節(jié)點(diǎn)均開(kāi)啟AOF模式,并發(fā)200路,模擬不斷寫(xiě)Redis,持續(xù)15分鐘后,接口調(diào)用開(kāi)始出現(xiàn)大量失敗,且Redis所在的Linux虛擬服務(wù)器掛起。
接口報(bào)錯(cuò)如下:
{"data":null,"base":{"returndesc":"系統(tǒng)異常","returncode":"999999"},"qrybase":null}
Biz(dubbo)接口報(bào)錯(cuò)如下:
2015-06-05?11:28:28.760?[DubboServerHandler-X.X.X.X:20882-thread-173]?ERROR??-?error?while?validate?jedis!
redis.clients.jedis.exceptions.JedisConnectionException:?java.net.SocketTimeoutException:?Read?timed?out
原因分析:
從dubbo接口報(bào)錯(cuò)信息來(lái)看,是由于接口API操作Redis超時(shí)導(dǎo)致。從系統(tǒng)日志和IO監(jiān)控來(lái)看,均說(shuō)明上述問(wèn)題是由于IO瓶頸(系統(tǒng)IO過(guò)于繁忙)所致,如下所示:


從系統(tǒng)日志也能看出,IO阻塞時(shí)間超過(guò)了120秒,由于系統(tǒng)安全機(jī)制導(dǎo)致機(jī)器掛起。
總結(jié)
測(cè)試結(jié)果證明AOF模式存在最明顯缺陷,即訪(fǎng)問(wèn)壓力大時(shí)IO會(huì)成為性能瓶頸,進(jìn)而導(dǎo)致服務(wù)不可用。
3、緩解方案(不能根本解決問(wèn)題)
編輯/etc/sysctl.conf ,添加如下配置:
vm.dirty_background_ratio?=?5
vm.dirty_ratio?=?10
然后sysctl -p 使配置文件生效。
問(wèn)題2描述:
無(wú)論采用AOF模式還是RDB(快照模式),當(dāng)兩文件(.aof或.rdb)大小超過(guò)系統(tǒng)內(nèi)存80%,Redis進(jìn)程會(huì)被系統(tǒng)Kill掉,導(dǎo)致服務(wù)不可用。
總結(jié)
上述問(wèn)題說(shuō)明我們?cè)谑褂肦edis時(shí)需要事先做好系統(tǒng)內(nèi)存的容量規(guī)劃,因?yàn)橐坏㏑edis宕掉會(huì)導(dǎo)致大量數(shù)據(jù)丟失且是不可恢復(fù)的。
本文來(lái)自PHP中文網(wǎng)的redis教程?欄目:https://www.php.cn/redis/