<noframes id="bhrfl"><address id="bhrfl"></address>

    <address id="bhrfl"></address>

    <noframes id="bhrfl"><address id="bhrfl"><th id="bhrfl"></th></address>

    <form id="bhrfl"><th id="bhrfl"><progress id="bhrfl"></progress></th></form>

    <em id="bhrfl"><span id="bhrfl"></span></em>

    全部
    常見問題
    產品動態
    精選推薦

    Spring Boot中的緩存支持(二)使用Redis做集中式緩存

    管理 管理 編輯 刪除

    準備工作

    可以下載案例Chapter4-4-1,進行下面改造步驟。先來回顧一下在此案例中,我們做了什么內容:

    • 引入了spring-data-jpaEhCache
    • 定義了User實體,包含id、name、age字段
    • 使用spring-data-jpa實現了對User對象的數據訪問接口UserRepository
    • 使用Cache相關注解配置了緩存
    • 單元測試,通過連續的查詢和更新數據后的查詢來驗證緩存是否生效

    #開始改造

    • 刪除EhCache的配置文件src/main/resources/ehcache.xml
    • pom.xml中刪除EhCache的依賴,增加redis的依賴:
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-redis</artifactId>
    </dependency>
    • application.properties中增加redis配置,以本地運行為例,比如:
    spring.redis.host=localhost
    spring.redis.port=6379
    spring.redis.pool.max-idle=8
    spring.redis.pool.min-idle=0
    spring.redis.pool.max-active=8
    spring.redis.pool.max-wait=-1

    我們需要做的配置到這里就已經完成了,Spring Boot會在偵測到存在Redis的依賴并且Redis的配置是可用的情況下,使用RedisCacheManager初始化CacheManager。

    為此,我們可以單步運行我們的單元測試,可以觀察到此時CacheManager的實例是org.springframework.data.redis.cache.RedisCacheManager,并獲得下面的執行結果:

    Hibernate: insert into user (age, name) values (?, ?)
    Hibernate: select user0_.id as id1_0_, user0_.age as age2_0_, user0_.name as name3_0_ from user user0_ where user0_.name=?
    第一次查詢:10
    第二次查詢:10
    Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?
    Hibernate: update user set age=?, name=? where id=?
    第三次查詢:10
    

    可以觀察到,在第一次查詢的時候,執行了select語句;第二次查詢沒有執行select語句,說明是從緩存中獲得了結果;而第三次查詢,我們獲得了一個錯誤的結果,根據我們的測試邏輯,在查詢之前我們已經將age更新為20,但是我們從緩存中獲取到的age還是為10。

    #問題思考

    為什么同樣的邏輯在EhCache中沒有問題,但是到Redis中會出現這個問題呢?

    在EhCache緩存時沒有問題,主要是由于EhCache是進程內的緩存框架,第一次通過select查詢出的結果被加入到EhCache緩存中,第二次查詢從EhCache取出的對象與第一次查詢對象實際上是同一個對象(可以在使用Chapter4-4-1工程中,觀察u1==u2來看看是否是同一個對象),因此我們在更新age的時候,實際已經更新了EhCache中的緩存對象。

    而Redis的緩存獨立存在于我們的Spring應用之外,我們對數據庫中數據做了更新操作之后,沒有通知Redis去更新相應的內容,因此我們取到了緩存中未修改的數據,導致了數據庫與緩存中數據的不一致。

    因此我們在使用緩存的時候,要注意緩存的生命周期,利用好上一篇上提到的幾個注解來做好緩存的更新、刪除

    #進一步修改

    針對上面的問題,我們只需要在更新age的時候,通過@CachePut來讓數據更新操作同步到緩存中,就像下面這樣:


    @CacheConfig(cacheNames = "users")
    public interface UserRepository extends JpaRepository<User, Long> {
    
        @Cacheable(key = "#p0")
        User findByName(String name);
    
        @CachePut(key = "#p0.name")
        User save(User user);
    
    }
    

    在redis-cli中flushdb,清空一下之前的緩存內容,再執行單元測試,可以獲得下面的結果:


    Hibernate: insert into user (age, name) values (?, ?)
    第一次查詢:10
    第二次查詢:10
    Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.name as name3_0_0_ from user user0_ where user0_.id=?
    Hibernate: update user set age=?, name=? where id=?
    第三次查詢:20
    

    可以看到,我們的第三次查詢獲得了正確的結果!同時,我們的第一次查詢也不是通過select查詢獲得的,因為在初始化數據的時候,調用save方法時,就已經將這條數據加入了redis緩存中,因此后續的查詢就直接從redis中獲取了。

    本文內容到此為止,主要介紹了為什么要使用Redis做緩存,以及如何在Spring Boot中使用Redis做緩存,并且通過一個小問題來幫助大家理解緩存機制,在使用過程中,一定要注意緩存生命周期的控制,防止數據不一致的情況出現。

    #代碼示例

    本文的相關例子可以查看下面倉庫中的chapter4-4-2目錄:


    請登錄后查看

    CRMEB 最后編輯于2025-01-20 11:57:03

    快捷回復
    回復
    回復
    回復({{post_count}}) {{!is_user ? '我的回復' :'全部回復'}}
    排序 默認正序 回復倒序 點贊倒序

    {{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level }}

    作者 管理員 企業

    {{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推薦': '推薦'}}
    {{item.is_suggest == 1? '取消推薦': '推薦'}}
    沙發 板凳 地板 {{item.floor}}#
    {{item.user_info.title || '暫無簡介'}}
    附件

    {{itemf.name}}

    {{item.created_at}}  {{item.ip_address}}
    打賞
    已打賞¥{{item.reward_price}}
    {{item.like_count}}
    {{item.showReply ? '取消回復' : '回復'}}
    刪除
    回復
    回復

    {{itemc.user_info.nickname}}

    {{itemc.user_name}}

    回復 {{itemc.comment_user_info.nickname}}

    附件

    {{itemf.name}}

    {{itemc.created_at}}
    打賞
    已打賞¥{{itemc.reward_price}}
    {{itemc.like_count}}
    {{itemc.showReply ? '取消回復' : '回復'}}
    刪除
    回復
    回復
    查看更多
    打賞
    已打賞¥{{reward_price}}
    948
    {{like_count}}
    {{collect_count}}
    添加回復 ({{post_count}})

    相關推薦

    快速安全登錄

    使用微信掃碼登錄
    {{item.label}} 加精
    {{item.label}} {{item.label}} 板塊推薦 常見問題 產品動態 精選推薦 首頁頭條 首頁動態 首頁推薦
    取 消 確 定
    回復
    回復
    問題:
    問題自動獲取的帖子內容,不準確時需要手動修改. [獲取答案]
    答案:
    提交
    bug 需求 取 消 確 定
    打賞金額
    當前余額:¥{{rewardUserInfo.reward_price}}
    {{item.price}}元
    請輸入 0.1-{{reward_max_price}} 范圍內的數值
    打賞成功
    ¥{{price}}
    完成 確認打賞

    微信登錄/注冊

    切換手機號登錄

    {{ bind_phone ? '綁定手機' : '手機登錄'}}

    {{codeText}}
    切換微信登錄/注冊
    暫不綁定
    亚洲欧美字幕
    CRMEB客服

    CRMEB咨詢熱線 咨詢熱線

    400-8888-794

    微信掃碼咨詢

    CRMEB開源商城下載 源碼下載 CRMEB幫助文檔 幫助文檔
    返回頂部 返回頂部
    CRMEB客服