www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]1 刪除過(guò)期數(shù)據(jù) 我們?cè)O(shè)置Redis元素時(shí)可以指定過(guò)期時(shí)間,那么Redis如何刪除這些超時(shí)元素?Redis采用了兩種策略:定期刪除和惰性刪除。 (1) 定期刪除 Redis每隔一段時(shí)間就檢查哪些KEY已經(jīng)過(guò)期,如果過(guò)期就刪除。但是我們來(lái)設(shè)想一個(gè)問(wèn)題:如果Redis存儲(chǔ)KEY非常多


1 刪除過(guò)期數(shù)據(jù)

我們?cè)O(shè)置Redis元素時(shí)可以指定過(guò)期時(shí)間,那么Redis如何刪除這些超時(shí)元素?Redis采用了兩種策略:定期刪除和惰性刪除。

(1) 定期刪除

Redis每隔一段時(shí)間就檢查哪些KEY已經(jīng)過(guò)期,如果過(guò)期就刪除。但是我們來(lái)設(shè)想一個(gè)問(wèn)題:如果Redis存儲(chǔ)KEY非常多,僅僅超時(shí)檢查這項(xiàng)工作就會(huì)非常耗費(fèi)資源并嚴(yán)重影響服務(wù)能力。為了解決這個(gè)問(wèn)題Redis并不是檢查全量KEY而只是檢查部分,同時(shí)引入了惰性刪除策略。

(2) 惰性刪除

假設(shè)當(dāng)KEY1已經(jīng)過(guò)期,但是由于沒(méi)有被檢查到而未被刪除。那么當(dāng)程序訪問(wèn)KEY1時(shí),Redis會(huì)檢查KEY1是否過(guò)期,如果過(guò)期則刪除并不返回該值,這就是惰性刪除策略。結(jié)合定期刪除和惰性刪除兩種策略,就可以保證過(guò)期數(shù)據(jù)可以被刪除。


2 內(nèi)存淘汰

當(dāng)內(nèi)存不足時(shí)Redis會(huì)選擇一些緩存元素進(jìn)行刪除,那么哪些元素會(huì)被刪除?常見(jiàn)內(nèi)存淘汰策略如下:

no-enviction禁止驅(qū)逐數(shù)據(jù),新寫(xiě)入操作會(huì)報(bào)錯(cuò) volatile-lru從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集選擇最近最少使用的數(shù)據(jù)淘汰 volatile-ttl從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集選擇將要過(guò)期的數(shù)據(jù)淘汰 volatile-random從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集選擇任意的數(shù)據(jù)淘汰 allkeys-lru從數(shù)據(jù)集選擇最近最少使用的數(shù)據(jù)淘汰 allkeys-random從數(shù)據(jù)集選擇任意的數(shù)據(jù)淘汰

LRU(Least Recently Used)最近最少使用是比較常用的策略,我們使用JAVA代碼實(shí)現(xiàn)一個(gè)簡(jiǎn)單LRU策略,代碼原理并不復(fù)雜:使用一個(gè)鏈表存儲(chǔ)元素,表頭存儲(chǔ)最近訪問(wèn)的元素,這樣存儲(chǔ)的結(jié)果是表尾存儲(chǔ)最早訪問(wèn)的元素,表頭存儲(chǔ)最近訪問(wèn)的元素,當(dāng)超出鏈表容量時(shí)刪除表尾元素即可。

/** * 元素對(duì)象 * * @author 微信公眾號(hào)「IT徐胖子」 * */public class CacheElement { private String key; private Object value;  public CacheElement(String key, Object value) { this.key = key; this.value = value; }  public String getKey() { return key; }  public Object getValue() { return value; }  @Override public String toString() { return "Element [key=" + key + ", value=" + value + "]"; }} /** * LRU緩存策略 * * @author 微信公眾號(hào)「IT徐胖子」 * */public class LRUCache { private int capacity; private LinkedListcache;  public LRUCache(int capacity) { this.capacity = capacity; this.cache = new LinkedList<>(); }  /** * 獲取緩存元素 * * 找到元素后將元素從原位置刪除并插入到鏈表頭部(最近) */ public CacheElement get(String key) { Iteratoriterator = cache.iterator(); while (iterator.hasNext()) { CacheElement element = iterator.next(); if (element.getKey().equals(key)) { iterator.remove(); System.out.println("獲取到元素=" + element); put(element.getKey(), element.getValue()); return element; } } return null; }  /** * 存儲(chǔ)緩存元素 * * 新元素插入到鏈表頭部(最近) */ public boolean put(String key, Object value) { Iteratoriterator = cache.iterator(); while (iterator.hasNext()) { CacheElement element = iterator.next(); if (element.getKey().equals(key)) { iterator.remove(); break; } } if (capacity == cache.size()) { CacheElement deleteElement = cache.removeLast(); System.out.println("容量已滿(mǎn)刪除尾部元素=" + deleteElement); } CacheElement element = new CacheElement(key, value); cache.addFirst(element); System.out.println("插入頭部元素=" + element); return Boolean.TRUE; }  @Override public String toString() { return "LRUCache [capacity=" + capacity + ", cache=" + cache + "]"; }} /** * LRU測(cè)試實(shí)例 * * @author 微信公眾號(hào)「IT徐胖子」 * */public class TestCache { public static void main(String[] args) { System.out.println("==================存儲(chǔ)緩存元素=================="); LRUCache cache = new LRUCache(2); CacheElement element0 = new CacheElement("k0", "v0"); CacheElement element1 = new CacheElement("k1", "v1"); CacheElement element2 = new CacheElement("k2", "v2"); cache.put(element0.getKey(), element0.getValue()); cache.put(element1.getKey(), element1.getValue()); cache.put(element2.getKey(), element2.getValue());  System.out.println("==================獲取緩存元素=================="); System.out.println("獲取元素之前緩存對(duì)象=" + cache); cache.get("k1"); System.out.println("獲取元素之后緩存對(duì)象=" + cache); }} ==================存儲(chǔ)緩存元素==================插入頭部元素=Element [key=k0, value=v0]插入頭部元素=Element [key=k1, value=v1]容量已滿(mǎn)刪除尾部元素=Element [key=k0, value=v0]插入頭部元素=Element [key=k2, value=v2] ==================獲取緩存元素==================獲取元素之前緩存對(duì)象=LRUCache [capacity=2, cache=[Element [key=k2, value=v2], Element [key=k1, value=v1]]]獲取到元素=Element [key=k1, value=v1]插入頭部元素=Element [key=k1, value=v1]獲取元素之后緩存對(duì)象=LRUCache [capacity=2, cache=[Element [key=k1, value=v1], Element [key=k2, value=v2]]]



3 文章總結(jié)

本文分析了Redis緩存失效策略:刪除過(guò)期數(shù)據(jù)和內(nèi)存淘汰,并且使用JAVA代碼模擬了LRU策略實(shí)現(xiàn)。

這里我們可以做一個(gè)展開(kāi):Redis分布式鎖是否可靠。因?yàn)镽edis存在內(nèi)存淘汰機(jī)制,那么作為分布式鎖的KEY概率上會(huì)被淘汰,從而導(dǎo)致分布式鎖失效。所以?xún)H僅有分布式鎖是不夠的,我們還需要其它方法,例如設(shè)置數(shù)據(jù)庫(kù)層唯一索引,防止重復(fù)數(shù)據(jù)產(chǎn)生。

特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒(méi)關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:

Redis緩存失效策略思考

Redis緩存失效策略思考

Redis緩存失效策略思考

長(zhǎng)按訂閱更多精彩▼

Redis緩存失效策略思考

如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉