女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Redis緩存與Mysql如何保證一致性?

馬哥Linux運維 ? 來源:馬哥Linux運維 ? 2023-12-02 14:23 ? 次閱讀

前言

緩存和數據庫如何保證數據的一致是個很經典的問題,關于先更新緩存,還是先更新數據庫,或者先刪除緩存,還是先刪除數據的先后問題,再讀寫并發的場景下很難做到數據一致,我認為比較好的兩種方案:一種是我們經常說的延遲雙刪機制,但是這個延遲的時間是無法很準確的把握的,還有如果緩存刪除失敗了應該如何處理,總體來說還是不保險的;另外一種我認為是比較可行的方法,要引入阿里的canal,通過拉取binlog日志解析推送的MQ實現異步更新緩存,達到最終緩存和數據庫的一致性;

延遲雙刪策略

7da71cb2-903b-11ee-939d-92fbcf53809c.jpg

基本流程就是客戶端A請求,先去刪除緩存,然后將數據寫入數據庫,此時客戶端B查詢先去查詢緩存,緩存沒有返回,去查數據庫,此時還沒有完成主從同步,拿到是從庫的舊數據,然后將舊數據進行緩存,在客戶端A完成主從同步后,再次刪除緩存,這時數據才是一致的,但是重點就是在休眠的幾秒鐘,會造成數據的不一致性;

注意點:第二次刪除緩存如果失敗,那么緩存里面大概率還是舊數據;所以第二次緩存刪除重試的方法比較關鍵:

一種:失敗記錄寫表,起定時任務去掃描表進行重試,顯然這種方式并不會很好,會對數據庫造成很大的壓力;

另外一種:異步處理,利用消息隊列,將消息放在隊列中,緩解數據庫壓力,但是要增加對消息隊列的維護;

簡單寫個延遲雙刪的demo


@RestController
@RequestMapping
public class RedisController {


    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SysUserMapper sysUserMapper;

    @GetMapping
    public void duobleCancle() throws InterruptedException {
      
        redisTemplate.delete("1");
        
        SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(1));
      
        SysUser updateSysUser =new SysUser();
        updateSysUser.setUserName("Lxlxxx");
        updateSysUser.setEmail("@163.com");


        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.eq("userId",1);


        sysUserMapper.update(updateSysUser,updateWrapper);


        
        Thread.sleep(3000);

        redisTemplate.opsForValue().append(sysUser.getUserId(), JSON.toJSONString(sysUser));
 
        
        redisTemplate.delete("1");
    }

由此可見問題還是比較多的,如果這么在項目中使用這種寫法,那最終還是會讀取到臟數據;

基于訂閱binlog異步更新緩存

大致的流程是這樣的:

7dc6c760-903b-11ee-939d-92fbcf53809c.jpg

具體binlog訂閱實現

步驟:先安裝canal、然后安裝rabbitmq、然后就是mysql

Canal配置,因為canal支持 tcp, kafka, rocketMQ, rabbitMQ這四種異步的方式,這里我們使用 rabbitMQ,所以將serverMode配置成rabbitMQ


canal.ip = 1 
canal.serverMode = rabbitmq 
canal.mq.servers = 127.0.0.1 
canal.mq.vhost=canal  
canal.mq.exchange=exchange.trade 
canal.mq.username=guest 
canal.mq.password=guest 
---------------------------------------------------------------------------------
    
canal.instance.dbUsername=root
canal.instance.dbPassword=123456
canal.instance.mysql.slaveId=1234 
canal.instance.master.address=127.0.0.1:3306 
canal.instance.defaultDatabaseName=test 
canal.mq.topic=example 

mysql的my.cnf配置


log-bin=mysql-bin 
binlog-format=ROW 
server_id=1 

引入依賴,我分別引入的是redis、rabbitmq、mybatis-plus、fastsjon的包


        
            org.springframework.boot
            spring-boot-starter-web
        


        
            org.springframework.boot
            spring-boot-starter-data-redis
        


        
            org.springframework.boot
            spring-boot-starter-amqp
        


        
            com.alibaba
            fastjson
            1.2.3
        
                
            com.baomidou
            mybatis-plus-boot-starter
            ${mybatis.plus.version}
        

application.yml配置文件


spring:
  rabbitmq:
    virtual-host: canal
    host: 127.0.0.1
    publisher-confirms: true
  
  datasource:
    url: jdbc//127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  redis:
    host: 127.0.0.1

RabbitmqConfig配置


@Configuration
public class RabbitMqConfig {


    
    @Bean
    public Queue TestDirectQueue() {
        return new Queue("exchange.canal.queue",true);
    }


    
    @Bean
    DirectExchange TestDirectExchange() {
        return new DirectExchange("exchange.canal");
    }

    
    @Bean
    Binding bindingDirect() {
        return BindingBuilder.bind(TestDirectQueue()).to(TestDirectExchange()).with("example");
    }
    
}

RabbitMqListener監聽消息異步處理 canal拉取的binlog日志


@Component
@Slf4j
public class RabbitMqListener {

    @Autowired
    private StringRedisTemplate redisTemplate;


    @RabbitListener(queues = "exchange.canal.queue")
    public void process(Message message) {


        log.info("canal queue消費的消息" + message.getBody());
        Map map = JSON.parseObject(message.getBody(), Map.class);
        JSONArray array = null;
        String sqlType = (String) map.get("type");
        
        if (StringUtils.endsWithIgnoreCase("SELECT", sqlType)) {
            array = JSONArray.parseArray((String) map.get("data"));
        }
        if (null == array) {
            return;
        }
        JSONObject jsonObject = array.getJSONObject(0);
        
        if (StringUtils.endsWithIgnoreCase("UPDATE", sqlType)
                || StringUtils.endsWithIgnoreCase("INSERT", sqlType)) {
            redisTemplate.boundValueOps(jsonObject.get("code").toString()).set(jsonObject.toString());
            
        } else if (StringUtils.endsWithIgnoreCase("DELETE", sqlType)) {
            redisTemplate.delete(jsonObject.get("code").toString());
        }
        
        if (StringUtils.endsWithIgnoreCase("SELECT", sqlType)) {
            redisTemplate.boundValueOps(jsonObject.get("code").toString()).set(jsonObject.toString());
        } else {
            redisTemplate.delete(jsonObject.get("code").toString());
        }
    }
}

總結

在高并發的場景下緩存和數據庫的一致性的問題,永遠是個比較大的問題,在請求量很大的情況下,我們必須使用緩存來減少數據庫的壓力,但是我們需要對數據庫進行頻繁更新,其實基本保證不了瞬間的一致性,只能在最終保證一致性,通過消息異步的方式可以有效的控制緩存更新、刪除的可靠性。

審核編輯:黃飛

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據庫
    +關注

    關注

    7

    文章

    3900

    瀏覽量

    65751
  • MySQL
    +關注

    關注

    1

    文章

    849

    瀏覽量

    27509
  • Redis
    +關注

    關注

    0

    文章

    384

    瀏覽量

    11309

原文標題:Redis緩存與Mysql如何保證雙寫一致

文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    MySQLRedis延遲雙刪策略

    中,并且如果數據庫中的數據發生了改變則需要同步到redis中,同步過程中需要保證 MySQLredis數據一致性問題,在這個同步過程中出現
    的頭像 發表于 09-25 14:28 ?1122次閱讀
    <b class='flag-5'>MySQL</b>與<b class='flag-5'>Redis</b>延遲雙刪策略

    如何解決數據庫與緩存一致性

    緩存一致性 每次逢年過節的時候搶票非常艱難,放票的時候那么多人同時去搶票,如果所有人查詢、購票等都去訪問數據庫,那數據庫的壓力得有多大,這時候很多都會引入緩存, 把車票信息放入緩存,這
    的頭像 發表于 09-25 15:25 ?1323次閱讀
    如何解決數據庫與<b class='flag-5'>緩存</b><b class='flag-5'>一致性</b>

    Redis緩存MySQL數據不一致原因和解決方案

    高并發架構系列:Redis緩存MySQL數據一致性方案詳解
    發表于 03-27 15:55

    一致性非鎖定讀分析

    MySQL探秘(六)InnoDB一致性非鎖定讀
    發表于 09-17 08:39

    i.MX8M可以調用哪些刷新/無效緩存函數來保證緩存一致性

    的是,我們現在在較小的傳輸中遇到緩存問題。有時,當緩沖區被復制到用戶空間時,64 字節的數據沒有被正確的數據 buf 填充為 0xff。我們在次傳輸中傳輸了大約 1.1 MBytes,有時
    發表于 04-27 08:30

    加速器一致性接口

    提供異步緩存一致性直接訪問PS的入口。處理器可以標記ACP上的傳輸為一致性或非一致性。PL端的AXI主機通過ARUSERS[1:0]指示是否為一致性
    發表于 11-17 15:04 ?3943次閱讀

    Cache一致性協議優化研究

    問題的由來.總結了多核時代高速緩存一致性協議設計的關鍵問題,綜述了近年來學術界對一致性的研究.從程序訪存行為模式、目錄組織結構、一致性粒度、一致性
    發表于 12-30 15:04 ?0次下載
    Cache<b class='flag-5'>一致性</b>協議優化研究

    自主駕駛系統將使用緩存一致性互連IP和非一致性互連IP

    代ASIL B(D)自主駕駛系統將使用符合ISO 26262標準的緩存一致性互連IP和非一致性互連IP來實現。 美國加利福尼亞州坎貝爾2019年4月26日消息—Arteris IP
    的頭像 發表于 05-09 17:13 ?3399次閱讀

    管理基于Cortex?-M7的MCU的高速緩存一致性

    本文檔概述了不同場景下的高速緩存一致性問題,并就如何管理或避免高速緩存一致性問題提供了些方法建議。
    發表于 04-01 10:12 ?5次下載
    管理基于Cortex?-M7的MCU的高速<b class='flag-5'>緩存</b><b class='flag-5'>一致性</b>

    Redis緩存更新一致性的方式

    當執行寫操作后,需要保證緩存讀取到的數據與數據庫中持久化的數據是一致的,因此需要對緩存進行更新。
    的頭像 發表于 11-21 10:40 ?939次閱讀

    如何保障MySQLRedis的數據一致性

    我直接先拋下結論:在滿足實時的條件下,不存在兩者完全保存一致的方案,只有最終一致性方案。根據網上的眾多解決方案,總結出 6 種,直接看目錄。
    的頭像 發表于 03-14 16:48 ?1019次閱讀

    如何保證緩存一致性

    “ 本文的參考文章是2022年HOT 34上Intel Rob Blakenship關于CXL緩存一致性篇介紹。”
    的頭像 發表于 10-19 17:42 ?1537次閱讀
    如何<b class='flag-5'>保證</b><b class='flag-5'>緩存</b><b class='flag-5'>一致性</b>

    redismysql如何保持數據一致性

    RedisMySQL是兩個常用的數據庫系統,它們都有自己的特點和用途。在某些場景下,我們可能需要將RedisMySQL進行結合使用,并保持數據的
    的頭像 發表于 11-16 11:27 ?1129次閱讀

    redis集群中的hash一致性算法的理解

    Redis集群是種為了增強Redis的可擴展性和高可用而設計的集群方案。在Redis集群中,一致性
    的頭像 發表于 12-04 10:45 ?956次閱讀

    異構計算下緩存一致性的重要

    在眾多回復中,李博杰同學的回答被認為質量最高。他首先將緩存一致性分為兩個主要場景:是主機內CPU與設備間的一致性;二是跨主機的一致性
    的頭像 發表于 10-24 17:00 ?1433次閱讀
    異構計算下<b class='flag-5'>緩存</b><b class='flag-5'>一致性</b>的重要<b class='flag-5'>性</b>