Redis實(shí)現(xiàn)多級(jí)緩存
本文實(shí)例為大家分享了Redis實(shí)現(xiàn)多級(jí)緩存的具體代碼,供大家參考,具體內(nèi)容如下
一、多級(jí)緩存
1. 傳統(tǒng)緩存方案
請(qǐng)求到達(dá)tomcat后,先去redis中獲取緩存,不命中則去mysql中獲取
2. 多級(jí)緩存方案
- tomcat的請(qǐng)求并發(fā)數(shù),是遠(yuǎn)小于redis的,因此tomcat會(huì)成為瓶頸
- 利用請(qǐng)求處理每個(gè)環(huán)節(jié),分別添加緩存,減輕tomcat壓力,提升服務(wù)性能
二、JVM本地緩存
緩存是存儲(chǔ)在內(nèi)存中,數(shù)據(jù)讀取速度較快,能大量減少對(duì)數(shù)據(jù)庫(kù)的訪問(wèn),減少數(shù)據(jù)庫(kù)壓力
分布式緩存,如redis
- 優(yōu)點(diǎn): 存儲(chǔ)容量大,可靠性好,可以在集群中共享
- 缺點(diǎn): 訪問(wèn)緩存有網(wǎng)絡(luò)開銷
- 場(chǎng)景: 緩存數(shù)據(jù)量大,可靠性高,需要在集群中共享的數(shù)據(jù)
進(jìn)程本地緩存, 如HashMap, GuavaCache
- 優(yōu)點(diǎn):讀取本地內(nèi)存,沒(méi)有網(wǎng)絡(luò)開銷,速度更快
- 缺點(diǎn):存儲(chǔ)容量有限,可靠性低(如重啟后丟失),無(wú)法在集群中共享
- 場(chǎng)景:性能要求高,緩存數(shù)據(jù)量少
1. 實(shí)用案例
Caffeine是一個(gè)基于java8開發(fā)的,提供了近乎最佳命中率的高性能的本地緩存庫(kù)
目前spring內(nèi)部的緩存用的就是這個(gè)
<dependency> ? ? ?<groupId>com.github.ben-manes.caffeine</groupId> ? ? ?<artifactId>caffeine</artifactId> ? ? ?<version>3.0.5</version> ?</dependency>
package com.erick.cache; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import java.time.Duration; public final class CacheUtil { ? ? private static int expireSeconds = 2; ? ? public static Cache<String, String> cacheWithExpireSeconds; ? ? private static int maxPairs = 1; ? ? public static Cache<String, String> cacheWithMaxPairs; ? ? static { ? ? ? ? /*過(guò)期策略,寫完60s后過(guò)期*/ ? ? ? ? cacheWithExpireSeconds = Caffeine.newBuilder() ? ? ? ? ? ? ? ? .expireAfterWrite(Duration.ofSeconds(expireSeconds)) ? ? ? ? ? ? ? ? .build(); ? ? ? ? /*過(guò)期策略,達(dá)到最大值后刪除 ? ? ? ? ?* 1. 并不會(huì)立即刪除,等一會(huì)兒才會(huì)刪除 ? ? ? ? ?* 2. 會(huì)將之前存儲(chǔ)的數(shù)據(jù)刪除掉*/ ? ? ? ? cacheWithMaxPairs = Caffeine.newBuilder() ? ? ? ? ? ? ? ? .maximumSize(maxPairs) ? ? ? ? ? ? ? ? .build(); ? ? } ? ? /*從緩存中獲取數(shù)據(jù) ? ? ?* 1. 如果緩存中有,則直接從緩存中返回 ? ? ?* 2. 如果緩存中沒(méi)有,則去數(shù)據(jù)查詢并返回結(jié)果*/ ? ? public static String getKeyWithExpire(String key) { ? ? ? ? return cacheWithExpireSeconds.get(key, value -> { ? ? ? ? ? ? return getResultFromDB(); ? ? ? ? }); ? ? } ? ? public static String getKeyWithMaxPair(String key) { ? ? ? ? return cacheWithMaxPairs.get(key, value -> { ? ? ? ? ? ? return getResultFromDB(); ? ? ? ? }); ? ? } ? ? private static String getResultFromDB() { ? ? ? ? System.out.println("數(shù)據(jù)庫(kù)查詢"); ? ? ? ? return "db result"; ? ? } }
package com.erick.cache; import java.util.concurrent.TimeUnit; public class Test { ? ? @org.junit.Test ? ? public void test01() throws InterruptedException { ? ? ? ? CacheUtil.cacheWithExpireSeconds.put("name", "erick"); ? ? ? ? System.out.println(CacheUtil.getKeyWithExpire("name")); ? ? ? ? TimeUnit.SECONDS.sleep(3); ? ? ? ? System.out.println(CacheUtil.getKeyWithExpire("name")); ? ? } ? ? @org.junit.Test ? ? public void test02() throws InterruptedException { ? ? ? ? CacheUtil.cacheWithMaxPairs.put("name", "erick"); ? ? ? ? CacheUtil.cacheWithMaxPairs.put("age", "12"); ? ? ? ? System.out.println(CacheUtil.getKeyWithMaxPair("name")); ? ? ? ? System.out.println(CacheUtil.getKeyWithMaxPair("age")); ? ? ? ? TimeUnit.SECONDS.sleep(2); ? ? ? ? System.out.println(CacheUtil.getKeyWithMaxPair("name")); // 查詢不到了 ? ? ? ? System.out.println(CacheUtil.getKeyWithMaxPair("age")); ? ? } }
三、緩存一致性
1. 常見(jiàn)方案
1.1 設(shè)置有效期
- 給緩存設(shè)置有效期,到期后自動(dòng)刪除。再次查詢時(shí)可以更新
- 優(yōu)勢(shì):簡(jiǎn)單,方便
- 缺點(diǎn):時(shí)效性差,緩存過(guò)期之前可能不一致
- 場(chǎng)景:更新頻率低,時(shí)效性要求比較低的業(yè)務(wù)
1.2 同步雙寫
- 在修改數(shù)據(jù)庫(kù)的同時(shí),直接修改緩存
- 優(yōu)勢(shì):有代碼侵入,緩存與數(shù)據(jù)庫(kù)強(qiáng)一致性
- 缺點(diǎn):代碼進(jìn)入,耦合性高
- 場(chǎng)景:對(duì)一致性,失效性要求較高的緩存數(shù)據(jù)
1.3 異步通知
- 修改數(shù)據(jù)庫(kù)時(shí)發(fā)送事件通知,相關(guān)服務(wù)監(jiān)聽(tīng)到后修改緩存數(shù)據(jù)
- 優(yōu)勢(shì):低耦合,可以同時(shí)通知多個(gè)緩存服務(wù)
- 缺點(diǎn):時(shí)效性一把,可能存在緩存不一致問(wèn)題
- 場(chǎng)景:時(shí)效性一般,有多個(gè)服務(wù)需要同步
2. 基于Canal的異步通知
- 是阿里旗下的一款開源項(xiàng)目,基于java開發(fā)
- 基于數(shù)據(jù)庫(kù)增量日志解析,提供增量數(shù)據(jù)訂閱和消費(fèi)
- 基于mysql的主從備份的思想
2.1 mysql主從復(fù)制
2.2 canal 工作原理
canal 模擬 MySQL slave 的交互協(xié)議,偽裝自己為 MySQL slave ,向 MySQL master 發(fā)送dump 協(xié)議
MySQL master 收到 dump 請(qǐng)求, 開始推送 binary log 給 slave (即 canal )
canal 解析 binary log 對(duì)象(原始為 byte 流)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
利用控制臺(tái)如何對(duì)Redis執(zhí)行增刪改查命令
這篇文章主要給大家介紹了關(guān)于利用控制臺(tái)如何對(duì)Redis執(zhí)行增刪改查命令的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08Redis+Lua腳本實(shí)現(xiàn)計(jì)數(shù)器接口防刷功能(升級(jí)版)
這篇文章主要介紹了Redis+Lua腳本實(shí)現(xiàn)計(jì)數(shù)器接口防刷功能,使用腳本使得set命令和expire命令一同達(dá)到Redis被執(zhí)行且不會(huì)被干擾,在很大程度上保證了原子操作,對(duì)Redis實(shí)現(xiàn)計(jì)數(shù)器接口防刷功能感興趣的朋友一起看看吧2022-02-02Redis從單點(diǎn)到集群部署模式(單機(jī)模式?主從模式?哨兵模式)
這篇文章主要為大家介紹了Redis從單點(diǎn)集群部署模式(單機(jī)模式?主從模式?哨兵模式)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11Redis 單節(jié)點(diǎn)部署的實(shí)現(xiàn)
本文主要介紹了Redis 單節(jié)點(diǎn)部署的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06Redis實(shí)現(xiàn)分布式隊(duì)列淺析
Redis將數(shù)據(jù)存儲(chǔ)在內(nèi)存中,使得讀寫速度非??欤?jīng)常被用來(lái)做緩存系統(tǒng),這里我們將redis用來(lái)做一個(gè)分布式的消息隊(duì)列。這篇文章主要介紹了使用redis來(lái)作為消息隊(duì)列,并且進(jìn)行分布式主從配置,有需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2016-11-11