redis 中一個字段 修改map_CTO 指名點姓讓我帶頭沖鋒,熬了一個通宵,終于把Redis中7千萬個Key刪完了...

7370aa3d315795e469b3b545a01333d6.png

由于有一條業務線不理想,高層決定下架業務。對于我們技術團隊而言,其對應的所有服務器資源和其他相關資源都要釋放。

釋放了 8 臺應用服務器;1 臺 ES 服務器;刪除分布式定時任務中心相關的業務任務;備份并刪除 MySQL 數據庫;刪除 Redis 中相關的業務緩存數據。

CTO 指名點姓讓我帶頭沖鋒,才扣了我績效……好吧,沖~

其他都還好,不多時就解決了。唯獨這刪除 Redis 中的數據,害得我又熬了一個通宵,真是折煞我也!

# 難點分析

共用 Redis 服務集群

由于這條業務線的數據在 Redis 大概在 3G 左右,完全沒必要單獨建一個 Redis 服務集群,本著能節約就節約的態度,當初就決定和其他項目共享一個集群(這個集群配置:16 個節點,128G 內存,還算豪華吧~)

集群配置如下:

743169d05094e97d133704f5c9b0b4c7.png

在這種共用集群的情況下,導致無法簡單粗暴的釋放。因此只能選擇刪除 Key 的方式。

Key 命名不規范

要刪除 Key,首先就要精準的定位出哪些 Key 需要刪除,如果勿刪 Key,會影響到其他服務正常運轉!

如果 Key 本身設置了過期時間,但有些數據需是持久化的。然而那該死的項目經理一直催項目進度,導致開發人員在開發過程中很多地方都沒有設計到位。

比如 Redis Key 散落在項目代碼的每個角落;比如命名不是很規范。

真不知道是怎么 Review 代碼!哦,想必是沒有時間 Review,那該死的項目經理……

我隨便截個支付服務中的 Key 命名:

0d6448158eecdb1751d61b1692dba222.png

怎么樣?是不是覺得我們開發人員寫的代碼很 Low!別笑,在實際工作中,還有比這更 Low 的!希望你別遇到,不然真的很痛苦~

解決思路

經過以上的分析,我們簡單歸納如下:

我們真正關心的是那些未設置過期時間的 Key。

不能誤刪除 Key,否則下個月績效也沒了。

由于 Key 的命名及使用及其不規范,導致 Key 的定位難度很大。

看來,通過 Scan 命令掃描匹配 Key 的方式行不通了。只能通過人肉搜索了。

幸而 Idea 的搜索大法好,這個項目中使用的是 spring-boot-starter-data-redis。

因此我通過搜索 RedisTemplate 和 StringRedisTemplate 定位所有操作 Redis 的代碼。

具體步驟如下:

  • 通過這些代碼統計出 Key 的前綴并錄入到文本中。
  • 通過 Python 腳本把載入文中中的的 Key 并在后面加上“*”通配符。
  • 通過 Python 腳本通過 Scan 命令掃描出這些 Key。
  • 為了便于檢查,我們并沒有直接使用 Del 命令刪除 Key,在刪除 Key 之前,先通過 debug object key 的方式得到其序列化的長度,再執行刪除并返回序列化長度。這樣,我們就可以統計出所有 Key 的序列化長度來得到我們釋放的空間大小。

關鍵代碼如下:

def get_key(rdbConn,start):try:keys_list = rdbConn.scan(start,count=2000)return keys_listexcept Exception,e:print e
''' Redis DEBUG OBJECT command got key info '''
def get_key_info(rdbConn,keyName):try:rpiple = rdbConn.pipeline()rpiple.type(keyName)rpiple.debug_object(keyName)rpiple.ttl(keyName)key_info_list = rpiple.execute()return key_info_listexcept Exception,e:print "INFO : ",e
def redis_key_static(key_info_list):keyType = key_info_list[0]keySize = key_info_list[1]['serializedlength']keyTtl = key_info_list[2]key_size_static(keyType,keySize,keyTtl)

通過以上方式,能夠統計出究竟釋放了多少內存了。由于這個集群是有特么接近 7 千萬個 Key:

cf115c9e1fa80aa74d17b9d5ac3f3489.png

因此,等到了第二天天亮,我睡眼朦朧的看了一下,終于刪除完畢了,時間 07:13,早高峰即將來臨……

知恥而后勇

從來沒有經歷過因業務下線而清除資源的經驗。這次事情真心讓我覺得細微之處見真功夫的道理。

如果一開始我們就能夠遵循開發規范來使用和設計 Redis Key,也不至于浪費這么多時間。

為了讓 Key 的命名和使用更加規范,以及今后避免再次遇到這種情況,下午睡醒之后,我就在 Redis 公共組件庫里面添加了一個配置和自定義了 Key 序列化。

代碼如下:

@ConfigurationProperties(prefix = "spring.redis.prefix")
public class RedisKeyPrefixProperties {private Boolean enable = Boolean.TRUE;private String key;public Boolean getEnable() {return enable;}public void setEnable(Boolean enable) {this.enable = enable;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}
}
/*** @desc 對字符串序列化新增前綴* @author create by liming sun on 2020-07-21 14:09:51*/
public class PrefixStringKeySerializer extends StringRedisSerializer {private Charset charset = StandardCharsets.UTF_8;private RedisKeyPrefixProperties prefix;public PrefixStringKeySerializer(RedisKeyPrefixProperties prefix) {super();this.prefix = prefix;}@Overridepublic String deserialize(@Nullable byte[] bytes) {String saveKey = new String(bytes, charset);if (prefix.getEnable() != null && prefix.getEnable()) {String prefixKey = spliceKey(prefix.getKey());int indexOf = saveKey.indexOf(prefixKey);if (indexOf > 0) {saveKey = saveKey.substring(indexOf);}}return (saveKey.getBytes() == null ? null : saveKey);}@Overridepublic byte[] serialize(@Nullable String key) {if (prefix.getEnable() != null && prefix.getEnable()) {key = spliceKey(prefix.getKey()) + key;}return (key == null ? null : key.getBytes(charset));}private String spliceKey(String prefixKey) {if (StringUtils.isNotBlank(prefixKey) && !prefixKey.endsWith(":")) {prefixKey = prefixKey + "::";}return prefixKey;}
}

使用效果:為了避免再次發生這種工作低效而又不得不做的事情,我們在開發規范中規定,新項目中 Redis 的使用必須設置此配置,前綴就設置為:項目編號。

另外,一個模塊中的 Key 必須統一定義在二方庫的 RedisKeyConstant 類中。

配置如下:

spring: redis: prefix:enable: truekey: E00P01
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);// 支持key前綴設置的key SerializerredisTemplate.setKeySerializer(new PrefixStringKeySerializer());redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());return redisTemplate;
}

通過以上方式,我們至少可以從項目維度來區分出 Key,避免了多個項目之間共用同一個集群時而導致重復 Key 的問題。

從項目維度對 Key 進行了劃分。更方便管理和運維。如果對于 Key 的管理粒度要求更細,我們甚至可以細化到具體業務維度。

我們在測試環境進行了壓測,增加 Key 前綴對 Redis 性能幾乎沒有影響。性能方面能接受。

總結

通過本次事情,我發現對于大多數開發者而言,差距其實不在于智力,而是在于態度。

比如這次事件暴露出來的問題:大家都知道要遵循開發規范,然而到了真正“打仗”的時候,負責這個項目的開發者卻沒有幾個人能始終如一的做好這些細微之事。

另外,Reviewer 的工作其實是極其重要的,他就像那“紀檢委”,如果“紀檢委”都放水睜一只眼閉一只眼,那麻煩可就大了!千里之提,毀于日常的點滴松懈啊!

經過這次事件之后,如果上天再給一次這樣的機會,我一定會對項目經理說:接著奏樂,接著舞!

編輯:浪漫先生

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/533406.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/533406.shtml
英文地址,請注明出處:http://en.pswp.cn/news/533406.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

太陽花圖片_長壽花扔水里,光長葉不開花?趕緊加點營養液

養個花可不簡單&#xff0c;春天一到還得操心換盆、換土&#xff0c;如果你像偷懶的話&#xff0c;還不如養些能水培的花&#xff0c;給它一杯水就夠了&#xff0c;實在太省心啦&#xff01;銅錢草銅錢草實在太好養了&#xff0c;摘一枝放在水杯里就能活&#xff0c;還挺有意境…

hystrix 全局熔斷_跟我學Spring Cloud(Finchley版)14Feign使用Hystrix

Feign默認已經整合了Hystrix&#xff0c;本節詳細探討Feign使用Hystrix的具體細節。服務降級1 加配置&#xff0c;默認Feign是不啟用Hystrix的&#xff0c;需要添加如下配置啟用Hystrix&#xff0c;這樣所有的Feign Client都會受到Hystrix保護&#xff01;feign:hystrix:enable…

ubuntu 改屏幕分辨率命令_Ubuntu被曝嚴重漏洞!!!

GitHub安全研究員Kevin Backhouse發現的一個Ubuntu系統大漏洞。無需系統密碼&#xff0c;就能添加新的sudo用戶、獲取root權限&#xff0c;事后還能刪除不留痕跡。這種攻擊方法非常簡單&#xff0c;Backhouse在官方博客中寫道&#xff1a;“使用終端中的一些簡單命令&#xff0…

swag您的裝置不支持_一件充滿意境的中國風水墨粒子、電子屏風交互裝置

不久前有人留言怎么用粒子做水墨&#xff0c;今天投石科技給大家分享個水墨粒子裝置作品案例&#xff0c;大家可以發揮自己的想象去做中國風的一些東西&#xff0c;希望能對大家有些幫助吧。《墨跡》這是一個數字山水畫的交互裝置&#xff0c;它通過攝像頭捕捉手部運動進行互動…

弱電工程集成商_弱電工程樓宇自控系統基礎知識培訓資料

前言&#xff1a;弱電行業里面樓宇自控系統是非常難的一個子系統&#xff0c;涉及到很多其他專業&#xff0c;樓宇自控系統的設計一般為廠家設計&#xff0c;但是也有系統集成商來設計的&#xff0c;樓宇自控系統主要學習它的控制原理&#xff0c;學習完以后學習DDC箱子的繪制&…

刪除單元格_VBA(實驗1)用VBA 刪除某列空單元格的3種方法:刪除法,轉移到其他列方法,數組方法...

1 要解決的問題&#xff1a;刪除某列中的空單元格/空行暫時只實現了刪除一列中的空行&#xff0c;并沒有實現多行的判斷空行和刪除方法。----之后再做更復雜的1.1 需求分析用VBA刪除如下內容&#xff0c;解決思路都不同刪除1列的空行&#xff08;本文要做的&#xff09;刪除整個…

安卓qpythonttsspeak_當python遇到Android手機 那么,萬物皆可盤

囂張開場今天不跟大家講python知識&#xff0c;是不很失望&#xff1f;No&#xff0c;看過了今天的內容&#xff0c;你python的裝13指數&#xff0c;至少上升1w&#xff0c;并附帶暴擊、濺射、眩暈、致盲效果。沒錯&#xff0c;就是這么囂張.....當python遇到安卓手機我們日常的…

winpe制作u盤啟動盤_怎么制作u盤啟動盤 u盤啟動盤制作方法【介紹】

使用u盤裝系統時就需要先將u盤制作成一個啟動u盤&#xff0c;這樣才能夠通過u盤啟動裝系統操作&#xff0c;那么 如何制作u盤啟動盤 呢?為此&#xff0c;今天我們就為小伙伴們詳細的介紹 怎樣制作u盤啟動盤 的操作。制作u盤啟動盤準備工作&#xff1a;① 、準備一個空間容量大…

插入空行_如何一鍵插入表格空行,這個方法才最高級!

100萬職場人都在看后臺回復禮包領199元職場干貨很久很久之前&#xff0c;小可教過大家如何一鍵刪除空行&#xff0c;回顧請戳→《如何一鍵刪除表格空行&#xff0c;這個方法才最高級&#xff01;》這次&#xff0c;小可反過來&#xff0c;教大家如何一鍵插入很多空行&#xff0…

的控制臺主題_【12.11最新版】芯片機/大氣層主題軟件NXThemesInstaller

Switch的主題的安裝和管理主要通過自制軟件——NXThemesInstaller軟件地址&#xff1a;https://github.com/exelix11/SwitchThemeInjector本文只傳了工具&#xff0c;主題需要自行去下載&#xff0c;可以按照自己喜歡的更換&#xff01;&#xff01;教程簡單概括如下這是最常見…

數據卡片_E015 如何批量匯總工作簿數據,形成獨立工作簿信息卡片

Hi&#xff0c;How are you doing?我是職場編碼&#xff08;CodeVoc&#xff09;。在E000中&#xff0c;我們介紹了Node.js、Ruby、Electron等工具下載安裝。這期&#xff0c;給你演示一下由Electron聯合Ruby制作的小工具。知乎視頻?www.zhihu.com借助Electron官方Demo&#…

linux 編譯3g驅動_linux重新編譯內核

1.內容簡介linux內核簡介linux內核版本號linux為什么重新編譯內核linux內核編譯模式linux內核功能劃分linux內核編譯步驟2linux內核簡介內核&#xff0c;是一個操作系統的核心。它負責管理系統的進程、內存、設備驅動、文件和網絡系統&#xff0c;決定著系統的性能和穩定性。3.…

r語言平均值顯著性檢驗_R語言:常用統計檢驗方法

轉自http://blog.sciencenet.cn/home.php?modspace&uid255662&doblog&id240107正態總體均值的假設檢驗t檢驗單個總體例一某種元件的壽命X(小時)&#xff0c;服從正態分布&#xff0c;N(mu,sigma^2)&#xff0c;其中mu,sigma^2均未知&#xff0c;16只元件的壽命如下…

redis哨兵模式沒有切換主機_Redis哨兵(Sentinel)模式

Redis哨兵(Sentinel)模式在這里插入圖片描述一、主從復制高可用當我們使用主從復制出現的問題手動故障轉移寫能力和存儲能力受限主從復制 -master 宕機故障處理主從切換技術的方法是&#xff1a;當主服務器宕機后&#xff0c;需要手動把一臺從服務器切換為主服務器&#xff0c;…

mysql rpm 安裝6_linux6.5 RPM方式安裝 mysql5.6

步驟一、檢查下linux是不是已經安裝了MySQL# rpm -qa|grep mysqlmysql-libs-5.1.71-1.el6.x86_64# rpm -e --nodeps mysql-libs-5.1.71-1.el6.x86_64 //卸載# find / -name mysql//有mysql文件夾的話&#xff0c;把mysql的文件夾刪掉步驟二、下載需要的安裝包&#xff0c;下載地…

php mysql 索引_MySQL索引

mysql 如何創建索引&#xff1f;1.添加PRIMARY KEY(主鍵索引)mysql>ALTER TABLE table_name ADD PRIMARY KEY ( column )2.添加UNIQUE(唯一索引)mysql>ALTER TABLE table_name ADD UNIQUE (column)3.添加INDEX(普通索引)mysql>ALTER TABLE table_name ADD INDEX index…

linux ftp mysql_linux下ftp和ftps以及ftp基于mysql虛擬用戶認證服務器的搭建

命令連接&#xff0c;控制連接&#xff1a;21/tcp數據連接: 主動模式,運行在20/tcp端口 和 被動模式,運行在隨機端口數據傳輸模式(自動模式)&#xff1a;有二進制(mp3,jpg等)和文本(html)兩種傳輸模式ftp服務器端程序&#xff1a;wu-ftpd&#xff1a;vsftpd pureftpd Filezilla…

阿里云rds for mysql平臺介紹_阿里云RDS for MySQL 快速入門——筆記

1初始化配置1.1設置白名單創建RDS實例后&#xff0c;需要設置RDS實例的白名單&#xff0c;以允許外部設備訪問該RDS實例。默認的白名單只包含默認IP地址127.0.0.1&#xff0c;表示任何設備均無法訪問該RDS實例。設置白名單包括兩種操作&#xff1a;設置IP白名單&#xff1a;添加…

mysql數據庫下載壓縮包_mysql 8.0.22 zip壓縮包版(免安裝)下載、安裝配置步驟詳解...

大家好&#xff0c;今天我在學習 MySQL 8.0.22安裝及配置遇到了一些問題&#xff0c;特地將我整個安裝過程分享出來希望可以幫助不會安裝的小伙伴&#x1f61c;。參考鏈接第一步 MySQL的下載進入MySQL官網下載&#xff0c;按下圖所示步驟操作&#xff0c;耐心等待下載完成就可以…

mysql 5.5 主從同步問題_MySQL 5.5 主從復制異步、半同步以及注意事項詳解

大綱一、前言二、Mysql 基礎知識三、Mysql 復制(Replication)四、Mysql 復制(Replication)類型五、Mysql 主從復制基本步驟六、Mysql 主從復制(異步)七、Mysql 主從復制(半同步)八、Mysql 復制工具九、Mysql 復制注意事項十、Mysql 復制過濾一、前言從這一篇博客開始我們就來學…