date: 2018-4-17 21:57:44
title: devops| redis 數(shù)據(jù)量暴漲進(jìn)行數(shù)據(jù)清理實戰(zhàn)
description: redis 作為程序員的 「瑞士軍刀」, 在現(xiàn)有業(yè)務(wù)中扮演著重要的角色. 為了避免觸雷, 「保衛(wèi)世界和平」, 對 redis 數(shù)據(jù)進(jìn)行分析并清理.
最近一段時間, 需求爆發(fā)式增長, 業(yè)務(wù)量也蹭蹭蹭上漲, 也伴隨著一些新的煩惱, 線上 redis 服務(wù), 頻繁觸發(fā)容量超出 80% 閥值報警. 而 redis 作為程序員的 「瑞士軍刀」, 在現(xiàn)有業(yè)務(wù)中扮演著重要的角色. 為了避免觸雷, 「保衛(wèi)世界和平」, 對 redis 數(shù)據(jù)進(jìn)行分析并清理.
快速尋找解決辦法
業(yè)務(wù)使用的阿里云的 redis 服務(wù), 報警也是使用阿里云上設(shè)置的, 比如下面這個模板:
容量不夠用, 首先想到的就是 redis 的淘汰機(jī)制, 對應(yīng)的設(shè)置:
各個淘汰機(jī)制不作過多介紹, 感興趣可以搜索網(wǎng)上更詳細(xì)的資料進(jìn)行了解. 現(xiàn)有的淘汰機(jī)制是符合現(xiàn)有業(yè)務(wù)特點的, 那就需要從其他地方下功夫了.
快速的在阿里云 redis 服務(wù)控制面板中瀏覽了一圈, 沒有發(fā)現(xiàn)相關(guān)的設(shè)置, 于是轉(zhuǎn)向百度. 嘗試 redis 容量超過閥值
redis 數(shù)據(jù)分析
redis 數(shù)據(jù)清理
等關(guān)鍵詞后, 依然沒有找到相關(guān)的答案.
最后, 向技術(shù)社區(qū)進(jìn)行求助 -- Swoole 開發(fā)者 微信交流群. 剛一拋出問題, 就找到需要的答案了.
@daydaygo 我搞過七芭,我們公司濫用redis,緩存和數(shù)據(jù)庫都在用刚照。最后搞了個腳本未檩,scan所有key了袁,統(tǒng)計前綴,然后根據(jù)前綴對應(yīng)到業(yè)務(wù)中,再挨個干掉。當(dāng)然淘汰機(jī)制和swap都得上戚宦。 -- Mr.Xie
@Mr. Xie 推薦工具 https://github.com/sripathikrishnan/redis-rdb-tools -- ForzaDong
這個有嘗試過,好像因為dump太大锈嫩,分析老是失敗受楼,就放棄了。 當(dāng)時有 20G, 現(xiàn)在減半了. -- Mr.Xie
2G跑了10多分鐘吧, 你分析前100就行了, 不用全部分析. -- ForzaDong
當(dāng)時內(nèi)存耗光呼寸,bgsave失敗艳汽,也沒有啟swap,比較緊急对雪,沒想那么多河狐。 -- Mr.Xie
代碼審計, redis 存儲空間的回收. 只會 set get 不考慮 del 的程序員, 不是好程序員. -- 如果的如果
用完就的釋放, 這要養(yǎng)成習(xí)慣. -- dbq
都知道重要, 但大多數(shù)都趕工期. -- zhanghan
bigscan? 使用 --bigkeys 參數(shù). -- Leandre
挑選了聊天中的部分, 不僅有解決方法, 還有寶貴的一線經(jīng)驗.
數(shù)據(jù)清理實戰(zhàn)
- 下載阿里云的備份數(shù)據(jù)到本地進(jìn)行分析
[圖片上傳失敗...(image-5fc52a-1523981140107)]
下載獲取 redis 的 .rdb
備份文件
有 go/php 2個語言支持, go 語言示例:
analysis := NewAnalysis()
//Open redis: 127.0.0.1:6379 without password
err := analysis.Open("127.0.0.1", 6379, "")
defer analysis.Close()
if err != nil {
fmt.Println("something wrong:", err)
return
}
//Scan the keys which can be split by '#' ':'
//Special pattern characters need to escape by '\'
analysis.Start([]string{"#", ":"})
//Find the csv file in default target folder: ./reports
//CSV file name format: redis-analysis-{host:port}-{db}.csv
//The keys order by count desc
analysis.SaveReports("./reports")
分析的效果:
PS: 需要將 .rdb
文件中的數(shù)據(jù), 導(dǎo)入到本地的 redis 服務(wù)器中, 然后使用此工具進(jìn)行分析
- 工具二(推薦): redis-rdb-tools
sripathikrishnan/redis-rdb-tools
阿里云幫助文檔 > 云數(shù)據(jù)庫 Redis 版 > 最佳實踐 > Redis 內(nèi)存分析方法
推薦使用此工具, 阿里云的幫助文檔列舉了詳細(xì)的使用方法, 這里就不過多解釋了.
PS: 阿里云幫助文檔有空可以多看看, 尤其是里面的 最佳實踐
寫在最后
redis 作為程序員的 「瑞士軍刀」, 對它多一點了解, 可以說是 性價比很高 的一件事兒, 這里再推薦幾個資源:
aliyun redis 開發(fā)規(guī)范
如何提取Redis中的大KEY -- 使用 –bigkeys 參數(shù)
Redis危險命令重命名、禁用
keys *
使用 scan
命令進(jìn)行重寫(PHP版本, 代碼來自 yuchen 大大):
public static function redisKeys($redis, $pattern, $step, $callback=NULL) {
if (strpos($pattern, '*') === false) {
throw new \ErrorException('none * in pattern');
}
$ret = [];
$cursor = 0;
do {
$redis_query = $redis->scan($cursor, 'match', $pattern, 'count', $step);
if (! empty($redis_query[1])) {
if (is_callable($callback)) {
$_ret = call_user_func($callback, $redis_query[1]);
if ( false === $_ret ) {
break;
}
else if ((! empty($_ret)) && is_array($_ret)) {
$ret = array_merge($ret, $_ret);
}
}
else {
$ret = array_merge($ret, $redis_query[1]);
}
}
$cursor = $redis_query[0];
} while ($cursor != 0);
return $ret;
}
感謝 Swoole 開發(fā)者微信交流群 里的各位大大給出的指導(dǎo)~