Redis EXISTS命令耗時過長case排查

來源:互聯網
上載者:User

標籤:

一、背景

redis慢日誌分析平台上線後,隨便看了一下,發現onestore使用的緩衝叢集,存在大量的EXISTS命令慢查詢的情況:


平均每個EXISTS命令需要13ms,最大耗時近20ms。這個結果很不科學啊,EXISTS命令只是執行一次hash尋找操作,應該是us層級。

和相關同學瞭解業務背景如下:

- 業務是userfeed,存放使用者發表的動態

- 使用zset儲存一個使用者發表的所有動態,key是使用者id,集合中對應的是feedid。如果使用者發表的動態很多,zset也很大

- redis叢集作為onestore的緩衝,到期時間是10分鐘

- 在訪問cache前會調用EXISTS查看是否命中,如果不命中就用onestore回填cache

由於一些使用者發表的動態很多(2W+),所以存在很多的ZADD慢查詢。

二、排查

1. redis的清除到期key的策略

- 被動方式:在事件迴圈中,每秒執行約10次,儘力刪除到期的key,會有漏掉的情況

- 從expire set中隨機檢查20個key

- 刪除到到期的key

- 如果超過25%的key都是到期了,就重複第一步(超過25%說明到期的key佔比很多)

- 主動方式:

- 如果該key在被動方式中漏過,在其再次被訪問時檢查並清除

2. 查看代碼

void existsCommand(redisClient *c) {    expireIfNeeded(c->db,c->argv[1]);  // 檢查該key是否到期,如果到期就delete掉    if (dbExists(c->db,c->argv[1])) {        addReply(c, shared.cone);    } else {        addReply(c, shared.czero);    }}
在EXISTS命令處理函數中實現了清除到期key的主動策略,會先調用expireIfNeeded函數檢查要訪問的key是否到期,如果到期就delete掉這個key。del命令在刪除元素很多的複合資料型別(list、hash、zset、set)時是一個很耗時的操作。由於存在元素很多的zset,和ZADD一樣,在刪除zset時需要一個一個遍曆所有元素,時間複雜度是大O(n)。由於這個刪除操作在EXISTS命令的處理函數中執行,所以導致EXISTS耗時過長。

3. redis慢日誌驗證

通過慢日誌可以驗證上述結論


- EXISTS先檢查‘user:94479529:feed’是否存在,該key已經到期,觸發主動到期機制,將該key刪除

- 從onestore擷取該key的資料,然後通過ZADD回填

三、風險

該叢集單個執行個體qps達到8k+,同時每天有10W+的慢查詢。在redis存在大量慢查詢時,會存在個別用戶端逾時的情況,導致請求失敗。

四、後續處理

1. 增加到期時間,由10分鐘到20分鐘

2. 對redis叢集擴容(試增加到期時間的效果而定)

對於redis刪除大key耗時的問題,redis作者提供瞭解決方案,具體就是使用非同步線程對大key進行刪除操作,避免阻塞主線程。

Redis EXISTS命令耗時過長case排查

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.