Redis的模糊查詢在生產(chǎn)環(huán)境出現(xiàn)嚴(yán)重的性能問題

Redis是一個高性能高效率的key-value存儲的nosql數(shù)據(jù)庫,由于數(shù)據(jù)是存儲在內(nèi)存中,因此訪問速度非???,由于項目涉及到數(shù)據(jù)庫的查詢非常多,而數(shù)據(jù)變大并不是非常頻繁,所以在項目中采用Redis分擔(dān)大部分MySQL的壓力。

在項目中實際使用我用的Redis提供的客戶端連接工具包jedis,在項目中引入jedis.Jar即可

public static Set searchLike(String like_key) {

Jedis jedis = RedisApi.getJedis();

boolean is_ok = true;

try {

if (jedis == null) {

return null;

}

return jedis.keys(like_key);

} catch (Exception e) {

// TODO: handle exception

is_ok = false;

return null;

} finally {

close(jedis, is_ok);

}

}

每當(dāng)用戶登錄成功之后,都會生成一個cookie,分別存在客戶端和Redis數(shù)據(jù)庫,cookie的key由cookie值+用戶ID組成:cookie字符串+"_"+用戶ID,例如用戶cookie為“d9fb0ea5333e854955fcf0a2183c5076”,用戶ID為 19092,

那Redis中存儲的key就是 d9fb0ea5333e854955fcf0a2183c5076_19092,最終的key-vlaue就是

{"d9fb0ea5333e854955fcf0a2183c5076_19092":d9fb0ea5333e854955fcf0a2183c5076}

而在用戶不斷的登錄成功,就不斷地產(chǎn)生這樣的記錄,久而久之,會積累出非常多的無用的key,浪費redis的空間,也加重了redis查詢的負(fù)擔(dān),因此想到使用Redis的模糊查詢來清掉無用的cookie的key

而Redis的客戶端jedis操作是通過jedis.keys(keys)來完成的,keys可以使用通配符來匹配Redis中的key

* 通配符說明:

*: 0到任意多個字符? searchLike("test*")

?: 1個字符? ? ?

比如現(xiàn)在需要清除某個用戶所有的無用的cookie的key,,則可以寫成“ *_19092 ”

String key_like="*_19092";

Set keys = RedisApi.searchLike(key_like);

這樣就可以查出所有這個用戶的keys,調(diào)用jedis提供的批量刪除key的方法即可達(dá)到目的

if (keys!=null && keys.size() > 0) {

String[] strArr = keys.toArray(new String[0]);// 字符串?dāng)?shù)組

// 刪除過期的key

RedisApi.removeString(strArr);

}

到這里從需求到邏輯到編碼一氣呵成,簡單測試沒什么問題后,就發(fā)布到線上,由于平時網(wǎng)站的流量不算非常高,所以運行了幾天也沒發(fā)生什么異常,直到今天早上,擁有幾十萬粉絲的公眾號發(fā)推文,推文的內(nèi)容直接鏈接到網(wǎng)站,因此說瞬間流量是非常高


運行了大約十分鐘之后,運營突然發(fā)瘋的過來說網(wǎng)站訪問非常慢,甚至出現(xiàn)錯誤碼,心里一慌,趕緊上去看日志,我了個乖乖啊,簡直是嚇人,error日志想流水一樣蹦出來,但五一不例外都是下面圖示的錯誤:從Redis池中獲取不大連接數(shù),馬上上redis服務(wù)器查看,發(fā)現(xiàn)CPU已經(jīng)到達(dá)了100%以上


能讓Redis的CPU到100%的,我想出了一下幾個可能:

1、連接數(shù)過多,占用連接的時間過長

2、存儲的值過大,存取均很占用CPU和內(nèi)存

3、慢查詢,事其它操作等待時間超時

4、redis阻塞,某個操作把Redis阻塞,導(dǎo)致CPU飆升

由于項目上線時間已經(jīng)很久,前三個可能基本都在平時查看Redis服務(wù)器性能的過程中排除掉,因此很大概率是第四個,突然想起前幾天做的功能,有個模糊查詢,該不是這個問題吧?我到網(wǎng)站輸入“Redis 模糊查詢 性能”,出來非常多關(guān)于redis模糊查詢性能急劇下降的的情況,而且建議生產(chǎn)環(huán)境下禁用redis的模糊查詢,于是我把模糊查詢這塊業(yè)務(wù)直接注釋掉,重新上線,運行了半天,再沒出現(xiàn)這個問題,因此可以斷定就是模糊查詢搞的鬼。

【替代方案】

有問題肯定是要解決的,既然模糊查詢行不通的,那就得想別的辦法達(dá)到目的,想到Redis有Set這這種存儲結(jié)構(gòu),因此可以把用戶的所有cookie key都放到一個用戶專屬的Set中,每次用戶登錄成功之后,都把之前Set里的cookie key清除,然后再把最新的key放進(jìn)去,這樣就可以達(dá)到同樣的目的了。

String setKey = Config.REDIS.prefix_customer_cookie_list + datacus.getId();

//取出所有的用戶的cookie key

Set list = RedisApi.getSet(setKey);

if (list != null && list.size() > 0) {

//刪除用戶所有的cookie key

RedisApi.removeFromSet(setKey, list.toArray(new String[0]));

}

//把最新的cookie key加入到Set中

RedisApi.addSet(setKey, token);

欲知大流量下的效果如何,請關(guān)注我哦,下回發(fā)推文后回復(fù)你。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 買個足球 ,是為了把你從電視機(jī)前拉過來;買雙球鞋,是為了你在運動中不至于傷著腳趾頭;陪你一起踢足球玩,是為...
    鄭子林閱讀 228評論 0 2
  • 結(jié)束了校園生活來到了麓谷實訓(xùn)中心,慢慢擺脫學(xué)生的固定思維,漸漸適應(yīng)職場般的生活。 今天實訓(xùn)經(jīng)理在課堂上跟我...
    文雅小小說閱讀 302評論 0 7

友情鏈接更多精彩內(nèi)容