欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Redis瘦身指南

 更新時(shí)間:2021年05月26日 14:12:36   作者:枕邊書(shū)  
Redis應(yīng)該是開(kāi)發(fā)者最常用的緩存服務(wù)器了,它豐富的數(shù)據(jù)結(jié)構(gòu),快速高效的內(nèi)存操作能幫助開(kāi)發(fā)者迅速完成復(fù)雜功能的設(shè)計(jì),作為一個(gè)內(nèi)存型數(shù)據(jù)庫(kù),Redis經(jīng)常會(huì)遇到內(nèi)存問(wèn)題,今天我們來(lái)談一下Redis常見(jiàn)的內(nèi)存滿的問(wèn)題,介紹一下給 Redis “瘦身”的通用方式。

Redis內(nèi)存回收

Redis 服務(wù)器的最大占用內(nèi)存量由配置項(xiàng) maxmemory 決定,我們可以通過(guò) config set maxmemory 2GB 的格式來(lái)配置。一旦 Redis 內(nèi)存滿,所有引起內(nèi)存增加的操作都會(huì)被返回 error。作為專業(yè) Redis 服務(wù)器我們通常將此項(xiàng)設(shè)置為0,以服務(wù)器系統(tǒng)內(nèi)存來(lái)作為限制;

那么 Redis 使用內(nèi)存達(dá)到了上限怎么辦?Redis 為我們提供了幾種選項(xiàng)以自動(dòng)回收內(nèi)存,可以通過(guò)配置項(xiàng) maxmemory-policy 來(lái)配置;

  • noeviction 不回收;
  • allkeys-lru 從所有鍵中刪除最近最少使用的鍵;
  • volatile-lru 從設(shè)置了過(guò)期時(shí)間的鍵中刪除最近最少使用的鍵;
  • allkeys-random 從所有鍵中隨機(jī)刪除;
  • volatile-random 從設(shè)置了過(guò)期時(shí)間的鍵中隨機(jī)刪除;
  • volatile-ttl 從設(shè)置了過(guò)期時(shí)間的鍵中選擇存活時(shí)間最短的鍵刪除;

最大內(nèi)存回收策略需要根據(jù)業(yè)務(wù)來(lái)配置,如果純粹做緩存,allkeys-lru無(wú)疑是最合適的。如果存儲(chǔ)了稍微重要的數(shù)據(jù),為了防止 Redis 誤刪一些重要鍵,則需要選用 noeviction;

allkeys-lru、allkeys-random 在內(nèi)存滿時(shí)都有鍵可刪,可以騰出內(nèi)存,但如果配置了其他的策略,數(shù)據(jù)庫(kù)用久了(根據(jù)業(yè)務(wù)量),隨著業(yè)務(wù)發(fā)展和數(shù)據(jù)積累,通常會(huì)累積到到服務(wù)器內(nèi)存占用率高,利用率低的情況,則可能會(huì)遇到內(nèi)存占用滿的問(wèn)題。

問(wèn)題原由

產(chǎn)生問(wèn)題的原因有:

持久鍵廢棄

這是導(dǎo)致此問(wèn)題的最常見(jiàn)情況。

有時(shí)候是開(kāi)發(fā)人員的鍋,開(kāi)發(fā)不規(guī)范,未給有時(shí)效性的鍵設(shè)置過(guò)期時(shí)間,后續(xù)又不進(jìn)行手動(dòng)刪除,鍵就成為無(wú)人管的孤兒鍵了。

還可能是整個(gè)業(yè)務(wù)慢慢被廢棄,不知道哪一天起,業(yè)務(wù)整體已不再維護(hù)了,一批鍵自然也就沒(méi)用了。比這更嚴(yán)重的是,如果使用 List 傳遞數(shù)據(jù),消費(fèi)進(jìn)程已被停止,但生產(chǎn)進(jìn)程未同步停止,還在往 Redis 里寫(xiě)數(shù)據(jù)。

過(guò)期鍵未回收

這個(gè)原因首先要談到 Redis 的兩種過(guò)期鍵刪除策略:

  • 惰性刪除:在讀取鍵時(shí)發(fā)現(xiàn)鍵已過(guò)期,則將其刪除。
  • 定期刪除:Redis 會(huì)從所有設(shè)置了過(guò)期時(shí)間的鍵中選取 100 個(gè),刪除已過(guò)期的鍵,如果已過(guò)期的鍵超過(guò) 25 個(gè),則再次進(jìn)行此操作。 此刪除操作由配置項(xiàng) hz 決定,Redis 默認(rèn)每秒進(jìn)行 10 次;

如果我們產(chǎn)生過(guò)期鍵的速度很快,最多可導(dǎo)致 Redis 25% 的過(guò)期鍵沒(méi)有被及時(shí)刪除。

遍歷清除垃圾鍵

由上,明白了問(wèn)題產(chǎn)生的原因,解決 Redis 內(nèi)存滿的方法就明確了:清除這些垃圾鍵。 于是就面臨著兩個(gè)問(wèn)題:

如何遍歷鍵

對(duì)于查找鍵,我們首先想到的是 KEYS,但 KEYS 的時(shí)間復(fù)雜度是O(n),n 是 Redis 內(nèi)鍵的總數(shù),如果 Redis 內(nèi)鍵很多還是會(huì)有性能問(wèn)題,導(dǎo)致其他命令被阻塞的。

這里介紹一個(gè)鍵遍歷命令: SCAN。

SCAN cursor:

0 => cursor, // cursor = 0 遍歷結(jié)束
1 => array(key1, key2...)

需要注意的是 SCAN 命令是在版本2.8.0 加入的,如果是之前的版本,可以考慮解析 Redis 的 RDB 文件來(lái)獲取所有的鍵。

如何判斷鍵是否垃圾

我們有三種異常鍵需要處理:

  • 過(guò)期鍵:這些鍵會(huì)在被 SCAN 到時(shí)被自動(dòng)刪除,不再考慮。如果是解析 RDB 文件獲取到的鍵,在查詢時(shí)也會(huì)被自動(dòng)刪除;
  • 長(zhǎng)時(shí)間未讀寫(xiě)的鍵,很可能是業(yè)務(wù)不再需要的鍵;
  • 占用大量?jī)?nèi)存的鍵,有可能是在不停地寫(xiě),但未消費(fèi)。

這里介紹 Redis 的另一個(gè)命令 OBJECT,使用它可以從內(nèi)部查看 key 對(duì)象的狀態(tài)。使用 OBJECT IDLETIME key 來(lái)獲取 key 的閑置時(shí)間,我們可以判斷 key 閑置時(shí)間大于一個(gè)時(shí)間段(根據(jù)業(yè)務(wù)自定)的為已廢棄。

此外還能使用 OBJECT REFCOUNT key獲取 key 引用所儲(chǔ)存的值的次數(shù),OBJECT ENCODING key 獲取 key 儲(chǔ)存的值所使用的內(nèi)部表示。

獲取鍵大小

而獲取 Redis 某鍵占用內(nèi)存大小,則通過(guò)另一個(gè)命令 DEBUG OBJECT 來(lái)獲取,此命令會(huì)返回比OBJECT命令更詳細(xì)的內(nèi)部數(shù)據(jù)。

DEBUG OBJECT test
Value at:0x7fb0ee16ebd0 refcount:1 encoding:embstr serializedlength:6 lru:12362780 lru_seconds_idle:4

結(jié)果包括內(nèi)存地址、引用數(shù)、內(nèi)部編碼表示、序列化后的長(zhǎng)度、最近最少使用標(biāo)識(shí)值,閑置時(shí)間,我們可以解析此結(jié)果串來(lái)獲取對(duì)應(yīng)的數(shù)據(jù)。

需要注意,key 作為復(fù)合鍵擁有大量字段時(shí)使用 DEBUG 命令計(jì)算內(nèi)存會(huì)使 Redis 阻塞較長(zhǎng)時(shí)間,且 Redis 官方并不建議在客戶端使用此命令。

我們也可以先使用 TYPE key 獲取鍵的類型,再根據(jù)類型獲取其鍵的大小,如對(duì)字符串使用LEN,對(duì) 哈希表使用HLEN。

要注意在刪除特別大的復(fù)合鍵時(shí),建議先逐步清空鍵內(nèi)的字段,防止因字段過(guò)多,Redis 阻塞較長(zhǎng)時(shí)間。

管道加速

Redis 支持 pipeline 管道技術(shù),一次 請(qǐng)求/響應(yīng) 服務(wù)器能實(shí)現(xiàn)處理并響應(yīng)多個(gè)請(qǐng)求。這樣就可以將多個(gè)命令同時(shí)發(fā)送到服務(wù)器,不等待回復(fù),直接在最后獲取多個(gè)結(jié)果。

PHP 中使用 MULTI(Redis::PIPELINE) 和 EXEC() 命令來(lái)實(shí)現(xiàn)管道;

腳本實(shí)現(xiàn)

下面是個(gè)簡(jiǎn)單的腳本:

$redis = new Redis();
$redis->connect('127.0.0.1');
do {
    $keys = $redis->scan($cursor);

    $pipeline = $redis->multi(Redis::PIPELINE);
    foreach ($keys as $key) {
        $idle_time = $redis->object('idletime', $key);
        if ($idle_time > 180 * 24 * 3600) {
            $pipeline->del($key);
        }
        // todo 判斷類型進(jìn)而判斷占用內(nèi)存大小,再刪除
    }
    $pipeline->exec();
} while ($cursor != 0);

從根源避免問(wèn)題

以上的腳本肯定也會(huì)在刪除鍵時(shí)影響 Redis 的效率,最好的情況還是從根源就避免此類情況,以下是一些建議:

  • 規(guī)范化開(kāi)發(fā);
  • 首先是鍵命名要規(guī)范,讓人見(jiàn)名知義,這樣在人工排錯(cuò)或刪除時(shí)也有判斷依據(jù),然后最好有完善的 Redis 鍵文檔,以保證業(yè)務(wù)在很長(zhǎng)時(shí)間,經(jīng)手多人后也能資料可查。
  • 使用 HashSet 替代 Key-Value;
  • 將業(yè)務(wù)中某一族的鍵以 HashSet 的方式存儲(chǔ),以替代普通的 key-value 類型。不僅可以省去為每個(gè)鍵設(shè)置前綴以節(jié)約內(nèi)存,也便于統(tǒng)一管理。
  • 有時(shí)效性的鍵注意設(shè)置過(guò)期時(shí)間;
  • 合理設(shè)置定時(shí)清除過(guò)期鍵頻率 hz,在 Redis 不做多余操作的情況下,使過(guò)期鍵盡量能被刪除;
  • 做好 Redis 內(nèi)存的監(jiān)控,在達(dá)到某個(gè)閾值時(shí)查找問(wèn)題并解決。

小結(jié)

Redis假死

我在使用守護(hù)進(jìn)程時(shí) Redis 有假死情況,PHP 和 Redis 都不報(bào)錯(cuò),但命令都返回 false,這種情況可以使用 Redis 的 ping() 命令,來(lái)探測(cè) Redis 連接是否還在,如果不在則再建立新的連接。此問(wèn)題很可能是由服務(wù)器配置引起的,如果您有知道此問(wèn)題的原由或有好的解決辦法,煩請(qǐng)指點(diǎn)一二。

危險(xiǎn)命令

不要在沒(méi)看文檔的情況下在線上使用 Redis 命令,例如 debug segfault,別問(wèn)我怎么知道的。

以上就是詳解Redis瘦身指南的詳細(xì)內(nèi)容,更多關(guān)于Redis瘦身指南的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Redis如何解決BigKey

    Redis如何解決BigKey

    在Redis的使用過(guò)程中,我們經(jīng)常會(huì)遇到BigKey, BigKey的大值會(huì)導(dǎo)致Redis內(nèi)存中產(chǎn)生大量不連續(xù)的碎片,降低內(nèi)存利用效率,本文主要介紹了Redis如何解決BigKey,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Redis實(shí)現(xiàn)多級(jí)緩存

    Redis實(shí)現(xiàn)多級(jí)緩存

    這篇文章主要為大家詳細(xì)介紹了Redis實(shí)現(xiàn)多級(jí)緩存,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • redis 解決key的亂碼問(wèn)題,并清理詳解

    redis 解決key的亂碼問(wèn)題,并清理詳解

    這篇文章主要介紹了redis 解決key的亂碼問(wèn)題,并清理詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-07-07
  • Redis緩存數(shù)據(jù)庫(kù)表(列單獨(dú)緩存)的示例代碼

    Redis緩存數(shù)據(jù)庫(kù)表(列單獨(dú)緩存)的示例代碼

    在Redis中緩存數(shù)據(jù)庫(kù)表數(shù)據(jù),而不使用JSON結(jié)構(gòu)來(lái)表示value,通常意味著我們會(huì)將數(shù)據(jù)庫(kù)表的每一行數(shù)據(jù)映射為Redis中的一個(gè)或多個(gè)鍵值對(duì),這篇文章主要介紹了Redis緩存數(shù)據(jù)庫(kù)表(列單獨(dú)緩存),需要的朋友可以參考下
    2024-03-03
  • 一篇文章帶你弄清楚Redis的精髓

    一篇文章帶你弄清楚Redis的精髓

    Redis是一個(gè)開(kāi)源的、支持網(wǎng)絡(luò)、基于內(nèi)存的鍵值對(duì)存儲(chǔ)系統(tǒng),它可以用作數(shù)據(jù)庫(kù)、緩存和消息中間件。它支持多種數(shù)據(jù)類型,包括字符串、散列、列表、集合、位圖等,擁有極快的讀寫(xiě)速度,并且支持豐富的特性,如事務(wù)、持久化、復(fù)制、腳本、發(fā)布/訂閱等。
    2023-02-02
  • 使用Jedis面臨的非線程安全問(wèn)題詳解

    使用Jedis面臨的非線程安全問(wèn)題詳解

    網(wǎng)上都說(shuō)jedis實(shí)例是非線程安全的,常常通過(guò)JedisPool連接池去管理實(shí)例,在多線程情況下讓每個(gè)線程有自己獨(dú)立的jedis實(shí)例,但都沒(méi)有具體說(shuō)明為啥jedis實(shí)例時(shí)非線程安全的,本文就來(lái)和大家詳細(xì)說(shuō)說(shuō)
    2022-12-12
  • Redis和MySQL保證雙寫(xiě)一致性的問(wèn)題解析

    Redis和MySQL保證雙寫(xiě)一致性的問(wèn)題解析

    Redis和MySQL的雙寫(xiě)一致性指的是在同時(shí)使用緩存和數(shù)據(jù)庫(kù)存儲(chǔ)數(shù)據(jù)的時(shí)候,保證Redis和MySQL中數(shù)據(jù)的一致性,那么如何才能保證他們的一致性呢,下面小編就來(lái)為大家詳細(xì)講講
    2023-11-11
  • redis?bitmap數(shù)據(jù)結(jié)構(gòu)之java對(duì)等操作詳解

    redis?bitmap數(shù)據(jù)結(jié)構(gòu)之java對(duì)等操作詳解

    bitmap是以其高性能出名。其基本原理是一位存儲(chǔ)一個(gè)標(biāo)識(shí),其他衍生知道咱就不說(shuō)了,而redis就是以這種原生格式存儲(chǔ)的,這篇文章主要介紹了redis?bitmap數(shù)據(jù)結(jié)構(gòu)之java對(duì)等操作,需要的朋友可以參考下
    2022-10-10
  • Redis?HyperLogLog數(shù)據(jù)統(tǒng)計(jì)輕量級(jí)解決方案詳解

    Redis?HyperLogLog數(shù)據(jù)統(tǒng)計(jì)輕量級(jí)解決方案詳解

    這篇文章主要為大家介紹了Redis?HyperLogLog數(shù)據(jù)統(tǒng)計(jì)輕量級(jí)解決方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Redis入門(mén)教程_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Redis入門(mén)教程_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Redis是一款開(kāi)源的、高性能的鍵-值存儲(chǔ)(key-value store)。下面通過(guò)本文大家分享Redis入門(mén)教程,感興趣的朋友參考下吧
    2017-08-08

最新評(píng)論