解決Redis持久化之大數(shù)據(jù)服務(wù)暫停問題
Redis持久化是有兩種方式:RDB和AOF
對這兩種方式的官方文檔的翻譯請看:
http://latteye.com/2011/11/redis-persistence.html
RDB就是快照存儲,比如“每1個小時對redis進行快照存儲”。那么,
save這個參數(shù)就應(yīng)該設(shè)置save 3600 1000 //前一次快照3600秒后,當有超過1000個key被改動的時候就進行一次快照更新RDB快照產(chǎn)生dump.rdb文件,當每到快照時間,更新文件。
AOF是存儲所有的寫操作,分兩個步驟:fsync和rewritefsync是把內(nèi)存中的寫操作寫入aof文件中rewrite是將寫操作合并,比如set aa 1; set aa 2; 兩個操作應(yīng)該寫成一個操作set aa 2;
如果數(shù)據(jù)量小的話,啥問題也沒有
現(xiàn)在假設(shè)服務(wù)器是20G內(nèi)存,而且服務(wù)器上僅僅只有跑redis一個占內(nèi)存的進程,就是說redis最多可以跑20G物理內(nèi)存現(xiàn)在壓入13G的redis數(shù)據(jù)(可以使用phpredis循環(huán)壓入,但是要注意設(shè)置php的運行內(nèi)存大小,最好使用pipeline的方式,否則php出現(xiàn)內(nèi)存不足的error)
嘗試1,我們只使用RDB的方式當進行快照的時候(測試時候可以把快照間隔時間定成30秒或更短)top查看進程
26376 test 16 0 13.5g 13g 7488 D 0.0 42.8 6:48.24 redis-server
32459 test 18 0 13.5g 13g 7200 D 1.3 42.8 0:23.22 redis-server
看到有兩個進程,同時在運行,并且占用同樣大小的內(nèi)存數(shù),和起來竟然占用26G之大~!
現(xiàn)在redis服務(wù)端上兩個進程都運行,看看客戶端:測試redis-cli set操作:
redis 10.1.0.108:6379> set test2 22
耗時(40.47s)近1分鐘
就是說在大數(shù)據(jù)量的時候,做RDB,redis服務(wù)會暫停近1分鐘!這個就是redis持久化的時候的服務(wù)暫?,F(xiàn)象。
好吧,為了保證數(shù)據(jù)容錯性,我們的快照一般是要頻繁快照的,所以暫停一分鐘是不可容忍的。
現(xiàn)在嘗試使用AOF+RDB:
1 將RDB的快照時間設(shè)置為1天(由于加上了AOF,所以這個時間是合理的)。
2 1次性壓入1000w左右的string數(shù)據(jù)到redis中(大概有5G數(shù)據(jù)量)
3 查看性能表現(xiàn):
第一個步驟fsync:
redis會從內(nèi)存中逐漸生成appendonly.aof 在這個過程我試了下set和get操作都是沒有暫停現(xiàn)象的(很好~?。?/p>
好了,現(xiàn)在appendonly.aof生成了,有5.7個G
-rw-r--r-- 1 root root 4186238374 Mar 6 15:50 appendonly.aof
第二個步驟:調(diào)用BGREWRITEAOF重寫aof文件
這個時候top查看:
看到也是兩個redis-server服務(wù)開著。說明rewrite的時候是fork一個子進程在rewrite的,主進程是進行著redis服務(wù)的。
這個時候redis-cli調(diào)用檢查
get操作:無延時
set操作:出現(xiàn)了延遲現(xiàn)象 ??!
這個說明AOF在重寫的時候會占用服務(wù)器的大量CPU和內(nèi)存資源,導(dǎo)致服務(wù)出現(xiàn)短暫暫?,F(xiàn)象!但是為什么get操作沒有出現(xiàn)延遲現(xiàn)象呢?參考官網(wǎng)文章,看到一個配置項:no-appendfsync-on-rewrite
這個配置項是設(shè)置在rewrite的時候是否對新的寫操作進行fsync。no表示進行fsync,yes表示不進行
默認是設(shè)置為no
現(xiàn)在將這個配置項設(shè)置為yes(我們對于rewrite的aof文件硬盤大小沒有很大要求)
重新進行測試:
對同樣的5.7G的AOF操作進行一次BGREWRITEAOF。
get操作:無延遲
set操作:無延遲
很好!說明在rewrite的時候如果不進行fsync操作,主進程和子進程是互不干擾的。
那么如果rewrite的時候?qū)π碌膶懖僮鞑贿M行fsync,那么新的aof文件里面是否會丟失這個寫操作呢?
答案是不會的,redis會將新的寫操作放在內(nèi)存中,等待rewrite操作完成的時候,將新操作直接掛在aof中。
好了,至此,這個問題應(yīng)該已經(jīng)可以過去了。
推薦幾個文章:
對數(shù)據(jù)持久化的一些想法:http://www.yiihsia.com/2011/04/%E5%AF%B9redis%E6%95%B0%E6%8D%AE%E6%8C%81%E4%B9%85%E5%8C%96%E7%9A%84%E4%B8%80%E4%BA%9B%E6%83%B3%E6%B3%95/
?。ㄟ@個文章提供了一個非常好的方法,當數(shù)據(jù)量大,內(nèi)存足夠的情況,一臺機子上盡量多開幾個redis,甚至可以考慮有幾個cpu就開幾個redis,這樣,每個redis的內(nèi)存量不會太大,就不會有大數(shù)據(jù)量服務(wù)暫停問題,這個也是考慮到了redis是單線程的,能盡量利用CPU)
redis的內(nèi)存陷阱:http://www.iteye.com/topic/808293
(這個文章很好解釋了問什么大數(shù)據(jù)量的時候會出現(xiàn)服務(wù)暫停)
Copy on write does not seem to work.: http://code.google.com/p/redis/issues/detail?id=150
出處:http://www.cnblogs.com/yjf512/
本文版權(quán)歸yjf512和cnBlog共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明