首頁  >  文章  >  資料庫  >  一起聊聊Redis快取的淘汰策略

一起聊聊Redis快取的淘汰策略

青灯夜游
青灯夜游轉載
2021-10-27 10:24:211743瀏覽

Redis 快取有哪些淘汰策略?這篇文章就來和大家一起聊聊Redis快取的淘汰策略,介紹快取策略設定建議,希望對大家有幫助!

一起聊聊Redis快取的淘汰策略

Redis(Remote Dictionary Server ),即遠端字典服務,是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。 【相關推薦:Redis影片教學

它具備以下的特徵:

  • 基於記憶體運行,具備高效能的特性
  • #支援分佈式,理論上可以無限拓展
  • key-value 儲存結構,查詢高效
  • 提供多種開發語言API, 容易和現有的業務系統整合。

通常在業務系統種用作分散式緩存,集中式 Session 存儲, 分散式鎖等運用場景。

不管是本地緩存還是分佈式緩存,為了確保較高性能,都是使用內存來保存數據,由於成本和內存限制,當存儲的數據超過緩存容量時,需要對緩存的數據進行剔除。一般的剔除策略有 FIFO 淘汰最早資料、LRU 剔除最近最少使用、和 LFU 剔除最近使用頻率最低的資料幾種策略。

Redis 快取淘汰策略觸發

在生產環境中我們是不允許 redis 出現 swap 行為的。所以一般會限制最大的使用內存,redis 提供了配置參數 maxmemory 來規定最大的使用內存。

以下設定皆為合法:

maxmemory 1000KB 
maxmemory 100MB 
maxmemory 1GB 
maxmemory 0  # 表示不做限制,一般不会用

redis.conf 設定檔如下

一起聊聊Redis快取的淘汰策略

8 種Redis 快取策略

  • volatile-lru 設定超時時間的資料中,刪除最不常用的資料;

  • allkeys-lru 查詢所有的key中最不常使用的資料進行刪除,這是應用最廣泛的策略;

  • volatile-random 在已經設定了超時的資料中隨機刪除;
  • ##allkeys- random 查詢所有的key 之後隨機刪除;
  • volatile-ttl 查詢全部設定超時時間的數據,追後馬上排序,將馬上將要過期的數據進行刪除操作;
  • noeviction (預設) 如果設定為該屬性,則不會進行刪除操作,如果記憶體溢出則報錯返回;
  • volatile-lfu 從所有配置了過期的時間的鍵中驅逐使用頻率最少的鍵;

  • allkeys-lfu 從所有鍵中驅逐使用頻率最少的鍵;

Redis 物種的LRU 與LFU 演算法

#LRU 演算法

Redis LRU 演算法不是精確的實作。這意味著 Redis 無法選擇

最佳的驅逐候選者,也就是過去造訪次數最多的造訪。相反,它會嘗試運行 LRU 演算法的近似值,方法是對少量密鑰進行採樣,然後逐出採樣密鑰中最好的(具有最早訪問時間)的密鑰。

然而,從 Redis 3.0 開始,演算法得到了改進,也可以選擇一些好的候選者進行驅逐。這提高了演算法的效能,使其能夠更接近真實 LRU 演算法的行為。

Redis LRU 演算法的重要之處在於,您

可以透過更改樣本數量來調整演算法的精度,以檢查每次驅逐。此參數由以下配置指令控制:

maxmemory-samples 5

Redis 之所以不使用真正的 LRU 實現,是因為它需要更多的記憶體。然而,對於使用 Redis 的應用程序,近似值實際上是等效的。以下是Redis所使用的LRU近似與真實LRU的比較圖。

一起聊聊Redis快取的淘汰策略

產生上述圖表的測試使用給定數量的鍵填入了 Redis 伺服器。從第一個到最後一個存取密鑰,因此第一個密鑰是使用 LRU 演算法驅逐的最佳候選者。後來又增加了 50% 的密鑰,以強制驅逐一半的舊密鑰。

您可以在圖中看到三種點,形成三個不同的帶。

    淺灰色帶是被驅逐的物件。
  • 灰色帶是未被驅逐的物件。
    綠色帶是新增的物件。
在理論上的 LRU 實作中,我們預期在舊金鑰中,前半部將過期。 Redis LRU 演算法只會在

機率上使舊金鑰過期。

LRU 只是一個模型,用於預測給定金鑰在未來被存取的可能性。此外,如果您的資料存取模式非常類似於冪律,則大多數存取將位於 LRU 近似演算法能夠很好處理的鍵集中。

缺點:可能會存在一定時間內大量的冷數資料被存取產生大量的熱點資料

LFU 算法

从 Redis 4.0 开始,可以使用新的最不常用驱逐模式。这种模式在某些情况下可能会更好(提供更好的命中率/未命中率),因为使用 LFU Redis 会尝试跟踪项目的访问频率,因此很少使用的项目会被驱逐,而经常使用的项目有更高的机会留在记忆中。

如果您认为在 LRU,最近访问过但实际上几乎从未被请求过的项目不会过期,因此风险是驱逐将来有更高机会被请求的密钥。LFU 没有这个问题,一般应该更好地适应不同的访问模式。

配置LFU模式,可以使用以下策略:

  • volatile-lfu 在具有过期集的键中使用近似 LFU 驱逐。
  • allkeys-lfu 使用近似 LFU 驱逐任何密钥。

LFU 类似于 LRU:它使用一个概率计数器,称为莫里斯计数器,以便仅使用每个对象的几位来估计对象访问频率,并结合衰减周期,以便计数器随着时间的推移而减少:在某些时候,我们不再希望将密钥视为经常访问的密钥,即使它们过去是这样,以便算法可以适应访问模式的转变。

这些信息的采样与 LRU 发生的情况类似(如本文档的前一部分所述),以便选择驱逐的候选人。

然而,与 LRU 不同的是,LFU 具有某些可调参数:例如,如果不再访问频繁项,它的排名应该以多快的速度降低?还可以调整 Morris 计数器范围,以便更好地使算法适应特定用例。

默认情况下,Redis 4.0 配置为:

  • 在大约一百万个请求时使计数器饱和。
  • 每一分钟衰减一次计数器。

这些应该是合理的值并经过实验测试,但用户可能希望使用这些配置设置以选择最佳值。

有关如何调整这些参数的说明可以redis.conf在源代码分发的示例文件中找到,但简单地说,它们是:

lfu-log-factor 10 
lfu-decay-time 1

衰减时间是显而易见的,它是计数器应该衰减的分钟数,当采样并发现它比该值更旧时。一个特殊值0意味着:每次扫描时总是衰减计数器,很少有用。

计数器对数因子会改变需要多少次命中才能使频率计数器饱和,这恰好在 0-255 的范围内。系数越高,需要越多的访问以达到最大值。根据下表,系数越低,低访问计数器的分辨率越好:

+--------+------------+------------+------------+------------+------------+
| factor | 100 hits   | 1000 hits  | 100K hits  | 1M hits    | 10M hits   |
+--------+------------+------------+------------+------------+------------+
| 0      | 104        | 255        | 255        | 255        | 255        |
+--------+------------+------------+------------+------------+------------+
| 1      | 18         | 49         | 255        | 255        | 255        |
+--------+------------+------------+------------+------------+------------+
| 10     | 10         | 18         | 142        | 255        | 255        |
+--------+------------+------------+------------+------------+------------+
| 100    | 8          | 11         | 49         | 143        | 255        |
+--------+------------+------------+------------+------------+------------+

淘汰最近一段时间被访问次数最少的数据,以次数作为参考。

缺点:

1. 最近加入的数据常常容易被剔除,因为其起始方法次数比较少,

2. 如果频率时间度量为 1 个小时,则平均一天每个小时内访问频率 1000 的热点数据可能会被 2个小时的一段时间访问的频率为 1001 的数据剔除掉。可能会出现一些临界值的数据。

缓存策略设置建议

建议:了解Redis 的淘汰策略之后,在平时使用尽量主动设置/更新 key 的 expire 时间主动剔除不活跃的旧数据, 有助于提升查询性能

更多编程相关知识,请访问:编程入门!!

以上是一起聊聊Redis快取的淘汰策略的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除