Redis緩存過(guò)期的實(shí)現(xiàn)示例
Redis緩存是一種常用的緩存技術(shù),可以提高系統(tǒng)性能和響應(yīng)速度。然而,如果不采取適當(dāng)?shù)倪^(guò)期策略,緩存可能會(huì)占據(jù)大量?jī)?nèi)存,并且數(shù)據(jù)也可能會(huì)過(guò)期并失效。
一、Redis緩存過(guò)期策略的基礎(chǔ)知識(shí)
了解Redis緩存過(guò)期策略的前提是必須掌握Redis內(nèi)存模型以及數(shù)據(jù)結(jié)構(gòu),在此我們不再贅述。Redis緩存過(guò)期策略的核心思想是根據(jù)key的過(guò)期時(shí)間來(lái)決定key是否被刪除的。當(dāng)一個(gè)key的過(guò)期時(shí)間到達(dá)指定時(shí)間后,Redis會(huì)自動(dòng)將其刪除。這個(gè)過(guò)程是由Redis內(nèi)部負(fù)責(zé)的,程序員只需要設(shè)定好key的過(guò)期時(shí)間即可。
二、Redis緩存過(guò)期策略常見的類型以及如何實(shí)現(xiàn)
1)TTL(Time-To-Live)
TTL是Redis最簡(jiǎn)單的過(guò)期策略之一,它需要程序員手動(dòng)為每個(gè)key設(shè)置過(guò)期時(shí)間。當(dāng)key的過(guò)期時(shí)間到達(dá)后,Redis會(huì)自動(dòng)將其刪除。我們可以使用TTL命令獲取key的剩余時(shí)間或者使用EXPIRE命令設(shè)置key的過(guò)期時(shí)間。例如:
# 設(shè)置 key 為 value, 并將過(guò)期時(shí)間設(shè)置為 10 秒鐘 SET key value EX 10 # 獲取 key 的剩余過(guò)期時(shí)間 TTL key
2)惰性刪除
惰性刪除策略也是Redis默認(rèn)的過(guò)期策略之一。它不會(huì)把所有的過(guò)期 key 都刪除掉,而是等到有客戶端來(lái)查詢這個(gè) key 的時(shí)候才檢查該 key 是否已過(guò)期,并在發(fā)現(xiàn)過(guò)期的情況下刪除該 key。因此惰性刪除存在缺陷:如果有大量的過(guò)期 key 沒(méi)有被查詢,就會(huì)占用過(guò)多的內(nèi)存空間。所以在某些場(chǎng)景中,需要結(jié)合其他策略來(lái)使用惰性刪除。
3)定期刪除
定期刪除是與惰性刪除相對(duì)應(yīng)的一種過(guò)期策略,它會(huì)每隔一段時(shí)間主動(dòng)檢查過(guò)期 key,并刪除過(guò)期的 key 。Redis會(huì)啟動(dòng)一個(gè)專門負(fù)責(zé)刪除過(guò)期 key 的線程,并且可以通過(guò)配置文件指定清除頻率(redis.conf文件中,default-db-deletion-size配上db * rows-per-second * 3600 )。與惰性刪除不同,定期刪除會(huì)消耗一定的CPU資源和IO資源,但相對(duì)惰性刪除而言,它可以更快的將大量過(guò)期 key 刪除掉。
二、Redis如何處理超時(shí)key
當(dāng)一個(gè)key過(guò)期后,程序員無(wú)需干預(yù),Redis會(huì)自動(dòng)開始進(jìn)行以下兩個(gè)操作:
1)簡(jiǎn)單地將該key打上過(guò)期標(biāo)記,并不立即從內(nèi)存中刪除;
2)通過(guò)惰性刪除或定期刪除策略,在之后的某個(gè)時(shí)間從內(nèi)存中清除帶有過(guò)期標(biāo)記的key。
需要注意的是,Redis并不能保證所有過(guò)期的key都能在第一時(shí)間被后臺(tái)線程清理掉。為了避免緩存泄漏和數(shù)據(jù)更新問(wèn)題,應(yīng)用程序在使用Redis緩存時(shí),最好添加邏輯判斷,比如在獲取value之前先檢查key是否存在或者手動(dòng)刪減過(guò)期key 。
三、基于時(shí)間的過(guò)期策略
1. 設(shè)置過(guò)期時(shí)間
在Redis中,可以使用EXPIRE和PEXPIRE命令為鍵設(shè)置生存時(shí)間,以秒或毫秒為單位。例如:
// 設(shè)置鍵為mykey的值,確保它在30秒之后過(guò)期
redisTemplate.opsForValue().set("mykey", "Hello, Redis!");
redisTemplate.expire("mykey", 30, TimeUnit.SECONDS);2. 查看剩余生存時(shí)間
可以使用TTL命令或PTTL命令來(lái)查看鍵的剩余生存時(shí)間(以秒或毫秒為單位)。例如:
// 查看mykey的生存時(shí)間(以秒為單位)
redisTemplate.ttl("mykey");
// 查看mykey的生存時(shí)間(以毫秒為單位)
redisTemplate.pttl("mykey");3. 取消過(guò)期時(shí)間
可以使用PERSIST命令來(lái)取消鍵的生存時(shí)間,使其永久保存。例如:
// 取消mykey的生存時(shí)間
redisTemplate.persist("mykey");四、基于LRU算法的淘汰機(jī)制
1. 設(shè)置最大內(nèi)存
可以使用maxmemory和maxmemory-policy兩個(gè)配置參數(shù)設(shè)置Redis的最大內(nèi)存和相應(yīng)的淘汰策略。例如:
# 設(shè)置Redis最大內(nèi)存為100MB maxmemory 100mb # 設(shè)置淘汰策略為L(zhǎng)RU maxmemory-policy allkeys-lru
2. 修改默認(rèn)淘汰策略
除了使用maxmemory-policy命令來(lái)設(shè)置全局的淘汰策略外,也可以通過(guò)將某些鍵標(biāo)記為VOLATILE來(lái)單獨(dú)設(shè)置LRU淘汰策略。例如:
// 將mykey的生存時(shí)間設(shè)置為10秒,并標(biāo)記為VOLATILE
redisTemplate.expire("mykey", 10, TimeUnit.SECONDS);
redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
// 將mykey標(biāo)記為VOLATILE
connection.setEx(redisTemplate.getKeySerializer().serialize("mykey"), 10000L,
redisTemplate.getValueSerializer().serialize("Hello, Redis!"));
return true;
}
});3. 查看Redis內(nèi)存使用情況
可以使用INFO命令或redis-cli工具來(lái)查看Redis的內(nèi)存使用情況。例如:
# 使用INFO命令查看Redis內(nèi)存使用情況
redisTemplate.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {
return connection.info();
}
});
# 使用redis-cli工具查看Redis內(nèi)存使用情況
$ redis-cli info memory五、通過(guò)Java代碼演示實(shí)操
以下是一個(gè)通過(guò)Java Redis API演示基于時(shí)間的過(guò)期策略和LRU淘汰機(jī)制的示例程序。
public class CacheDemo {
private static finalStringRedisTemplate redisTemplate = new StringRedisTemplate();
static {
// 設(shè)置Redis服務(wù)器的主機(jī)名和端口號(hào)
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("localhost", 6379);
// 創(chuàng)建連接池
LettuceConnectionFactory factory = new LettuceConnectionFactory(config);
factory.afterPropertiesSet();
// 設(shè)置RedisTemplate的連接工廠
redisTemplate.setConnectionFactory(factory);
redisTemplate.afterPropertiesSet();
}
public static void main(String[] args) {
// 設(shè)置鍵值對(duì)緩存
redisTemplate.opsForValue().set("key1", "value1");
redisTemplate.opsForValue().set("key2", "value2");
// 設(shè)置key1的生存時(shí)間為10秒,并標(biāo)記為VOLATILE
redisTemplate.expire("key1", 10, TimeUnit.SECONDS);
redisTemplate.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
connection.setEx(redisTemplate.getKeySerializer().serialize("key1"), 10000L,
redisTemplate.getValueSerializer().serialize("value1"));
return true;
}
});
// 查看key1的剩余生存時(shí)間
System.out.println(redisTemplate.getExpire("key1"));
// 設(shè)置Redis的最大內(nèi)存為10MB,淘汰策略為L(zhǎng)RU
redisTemplate.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {
connection.getConfig("maxmemory");
connection.getConfig("maxmemory-policy", "allkeys-lru");
return null;
}
});
// 查看Redis內(nèi)存使用情況
System.out.println(redisTemplate.execute(RedisServerCommands::info).get("used_memory"));
}
}六、總結(jié)
Redis緩存的過(guò)期策略是保證緩存可靠性和性能的關(guān)鍵之一。基于時(shí)間的過(guò)期策略通過(guò)設(shè)置生存時(shí)間來(lái)實(shí)現(xiàn),而基于LRU算法的淘汰機(jī)制則根據(jù)訪問(wèn)頻率和時(shí)間排序來(lái)刪除最近沒(méi)有使用的key。在實(shí)際使用中,可以結(jié)合兩種策略來(lái)避免出現(xiàn)緩存占據(jù)大量?jī)?nèi)存和過(guò)期失效等問(wèn)題。在Java中,可以使用RedisTemplate來(lái)對(duì)Redis進(jìn)行操作。通過(guò)設(shè)置鍵值對(duì)緩存、設(shè)置過(guò)期時(shí)間、取消過(guò)期時(shí)間、修改默認(rèn)淘汰策略和查看Redis內(nèi)存使用情況等操作,可以實(shí)現(xiàn)對(duì)緩存的控制和管理。
需要注意的是,在設(shè)置緩存過(guò)期時(shí)間和淘汰機(jī)制時(shí),應(yīng)根據(jù)業(yè)務(wù)場(chǎng)景和數(shù)據(jù)類型來(lái)選擇合適的時(shí)間和策略。如果需要緩存的數(shù)據(jù)變化頻繁,建議采用基于LRU算法的淘汰機(jī)制;如果數(shù)據(jù)比較固定或重要性較高,可以使用基于時(shí)間的過(guò)期策略。
到此這篇關(guān)于Redis緩存過(guò)期的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Redis緩存過(guò)期內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于redis實(shí)現(xiàn)的點(diǎn)贊功能設(shè)計(jì)思路詳解
點(diǎn)贊是我們現(xiàn)在經(jīng)常見到的一個(gè)效果,如朋友圈、微博都有點(diǎn)贊的效果,下面這篇文章主要跟大家分享了基于redis實(shí)現(xiàn)的點(diǎn)贊功能設(shè)計(jì)思路的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家實(shí)現(xiàn)點(diǎn)贊功能具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-05-05
高效異步redis客戶端aredis優(yōu)劣勢(shì)原理解析
這篇文章主要介紹了高效異步redis客戶端aredis優(yōu)劣勢(shì)原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
redis在spring boot中異常退出的問(wèn)題解決方案
這篇文章主要介紹了redis在spring boot中異常退出的問(wèn)題解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2025-05-05
Redis實(shí)現(xiàn)分布式鎖的幾種方法總結(jié)
這篇文章主要介紹了Redis實(shí)現(xiàn)分布式鎖的幾種方法總結(jié)的相關(guān)資料, Redis實(shí)現(xiàn)與Zookeeper實(shí)現(xiàn)和數(shù)據(jù)庫(kù)實(shí)現(xiàn),需要的朋友可以參考下2017-07-07

