您现在的位置是:Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款 > 

02 redis消息訂閱 阻塞(三分鐘讀懂redis數據庫)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款2024-05-25 13:40:31【】1人已围观

简介ve結點來的syn同步請求,會生成一個新的進程,將內存數據mp到文件上,然后再同步到slave結點中;AOF日志重寫:使用AOF持久化方式,做AOF文件重寫操作會創建新的進程做重寫;(重寫并不會去讀已

ve結點來的syn同步請求,會生成一個新的進程,將內存數據mp到文件上,然后再同步到slave結點中;

AOF日志重寫:使用AOF持久化方式,做AOF文件重寫操作會創建新的進程做重寫;(重寫并不會去讀已有的文件,而是直接使用內存中的數據寫成歸檔日志);

解決方案: 

為了應對大內存頁表復制時帶來的影響,有些可用的措施:

控制每個redis實例的最大內存量; 

不讓fork帶來的限制太多,可以從內存量上控制fork的時延; 

一般建議不超過20G,可根據自己服務器的性能來確定(內存越大,持久化的時間越長,復制頁表的時間越長,對事件循環的阻塞就延長) 

新浪微博給的建議是不超過20G,而我們虛機上的測試,要想保證應用毛刺不明顯,可能得在10G以下;

使用物理機; 

如果有的選,物理機當然是最佳方案,比上面都要省事; 

當然,虛擬化實現也有多種,除了Xen系統外,現代的硬件大部分都可以快速的復制頁表; 

但公司的虛擬化一般是成套上線的,不會因為我們個別服務器的原因而變更,如果面對的只有Xen,只能想想如何用好它;

杜絕新進程的產生,不使用持久化,不在主結點上提供查詢;實現起來有以下方案: 

1) 只用單機,不開持久化,不掛slave結點。這樣最簡單,不會有新進程的產生;但這樣的方案只適合緩存; 

如何來做這個方案的高可用? 

要做高可用,可以在寫redis的前端掛上一個消息隊列,在消息隊列中使用pub-sub來做分發,保證每個寫操作至少落到2個結點上;因為所有結點的數據相同,只需要用一個結點做持久化,這個結點對外不提供查詢; 

2) master-slave:在主結點上開持久化,主結點不對外提供查詢,查詢由slave結點提供,從結點不提供持久化;這樣,所有的fork耗時的操作都在主結點上,而查詢請求由slave結點提供; 

這個方案的問題是主結點壞了之后如何處理? 

簡單的實現方案是主不具有可替代性,壞了之后,redis集群對外就只能提供讀,而無法更新;待主結點啟動后,再繼續更新操作;對于之前的更新操作,可以用MQ緩存起來,等主結點起來之后消化掉故障期間的寫請求; 

如果使用官方的Sentinel將從升級為主,整體實現就相對復雜了;需要更改可用從的ip配置,將其從可查詢結點中剔除,讓前端的查詢負載不再落在新主上;然后,才能放開sentinel的切換操作,這個前后關系需要保證;

持久化造成的阻塞

執行持久化(AOF / RDB snapshot)對系統性能有較大影響,特別是服務器結點上還有其它讀寫磁盤的操作時(比如,應用服務和redis服務部署在相同結點上,應用服務實時記錄進出報日志);應盡可能避免在IO已經繁重的結點上開Redis持久化;

子進程持久化時,子進程的write和主進程的fsync沖突造成阻塞

在開啟了AOF持久化的結點上,當子進程執行AOF重寫或者RDB持久化時,出現了Redis查詢卡頓甚至長時間阻塞的問題, 此時, Redis無法提供任何讀寫操作;

原因分析: 

Redis 服務設置了 appendfsync everysec, 主進程每秒鐘便會調用 fsync(), 要求內核將數據”確實”寫到存儲硬件里. 但由于服務器正在進行大量IO操作, 導致主進程 fsync()/操作被阻塞, 最終導致 Redis 主進程阻塞.

redis.買粉絲nf中是這么說的: 

When the AOF fsync policy is set to always or everysec, and a background 

saving process (a background save or AOF log background rewriting) is 

performing a lot of I/O against the disk, in some Linux 買粉絲nfigurations 

Redis may block too long on the fsync() call. Note that there is no fix for 

this currently, as even performing fsync in a different thread will block 

our synchronous write(2) call. 

當執行AOF重寫時會有大量IO,這在某些Linux配置下會造成主進程fsync阻塞;

解決方案: 

設置 no-appendfsync-on-rewrite yes, 在子進程執行AOF重寫時, 主進程不調用fsync()操作;注意, 即使進程不調用 fsync(), 系統內核也會根據自己的算法在適當的時機將數據寫到硬盤(Linux 默認最長不超過 30 秒). 

這個設置帶來的問題是當出現故障時,最長可能丟失超過30秒的數據,而不再是1秒;

子進程AOF重寫時,系統的sync造成主進程的write阻塞

我們來梳理下: 

1) 起因:有大量IO操作write(2) 但未主動調用同步操作 

2) 造成kernel buffer中有大量臟數據 

3) 系統同步時,sync的同步時間過長 

4) 造成redis的寫aof日志write(2)操作阻塞; 

5) 造成單線程的redis的下一個事件無法處理,整個redis阻塞(redis的事件處理是在一個線程中進行,其中寫aof日志的write(2)是同步阻塞模式調用,與網絡的非阻塞write(2)要區分開來)

產生1)的原因:這是redis2.6.12之前的問題,AOF rewrite時一直埋頭的調用write(2),由系統自己去觸發sync。 

另外的原因:系統IO繁忙,比如有別的應用在寫盤;

解決方案: 

控制系統sync調用的時間;需要同步的數據多時,耗時就長;縮小這個耗時,控制每次同步的數據量;通過配置按比例(vm.dirty_background_ratio)或按值(vm.dirty_bytes)設置sync的調用閾值;(一般設置為32M同步一次) 

2.6.12以后,AOF rewrite 32M時會主動調用fdatasync;

另外,Redis當發現當前正在寫的文件有在執行fdatasync(2)時,就先不調用write(2),只存在cache里,免得被block。但如果已經超過兩秒都還是這個樣子,則會強行執行write(2),即使redis會被block住。

AOF重寫完成后合并數據時造成的阻塞

在bgrewriteaof過程中,所有新來的寫入請求依然會被寫入舊的AOF文件,同時放到AOF buffer中,當rewrite完成后,會在主線程把這部分內容合并到臨時文件中之后才rename成新的AOF文件,所以rewrite過程中會不斷打印"Background AOF buffer size: 80 MB, Background AOF buffer size: 180 MB",要監控這部分的日志。這個合并的過程是阻塞的,如果產生了280MB的buffer,在100MB/s的傳統硬盤上,Redis就要阻塞2.8秒;

解決方案: 

將硬盤設置的足夠大,將AOF重寫的閾值調高,保證高峰期間不會觸發重寫操作;在閑時使用crontab 調用AOF重寫命令;

三分鐘讀懂redis數據庫

1. 使用Redis有哪些好處?

(1) 速度快,因為數據存在內存中,類似于HashMap,HashMap的優勢就是查找和操作的時間復雜度都是O(1)

(2) 支持豐富數據類型,支持string,list,set,sorted set,hash

(3) 支持事務,操作都是原子性,所謂的原子性就是對數據的更改要么全部執行,要么全部不執行

(4) 豐富的特性:可用于緩存,消息,按key設置過期時間,過期后將會自動刪除

2. redis相比memcached有哪些優勢?

(1) memcached所有的值均是簡單的字符串,redis作為其替代者,支持更為豐富的數據類型

(2) redis的速度比memcached快很多

(3) redis可以持久化其數據

3. redis常見性能問題和解決方案:

(1) Master最好不要做任何持久化工作,如RDB內存快照和AOF日志文件

(2) 如果數據比較重要,某個Slave開啟AOF備份數據,策略設置為每秒同步一次

(3) 為了主從復制的速度和連接的穩定性,Master和Slave最好在同一個局域網內

(4) 盡量避免在壓力很大的主庫上增加從庫

(5) 主從復制不要用圖狀結構,用單向鏈表結構更為穩定,即:Master <- Slave1 <- Slave2 <- Slave3...

這樣的結構方便解決單點故障問題,實現Slave對Master的替換。如果Master掛了,可以立刻啟用Slave1做Master,其他不變。

4. MySQL里有2000w數據,redis中只存20w的數據,如何保證redis中的數據都是熱點數據

相關知識:redis 內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略。redis 提供 6種數據淘汰策略:

voltile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰

volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰

volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰

allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰

allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰

no-enviction(驅逐):禁止驅逐數據

相關推薦:《Python視頻教程》

5. Memcache與Redis的區別都有哪些?

1)

很赞哦!(34)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款的名片

职业:程序员,设计师

现居:四川成都成华区

工作室:小组

Email:[email protected]