国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Redis(十四)雙寫一致性工程案例

這篇具有很好參考價值的文章主要介紹了Redis(十四)雙寫一致性工程案例。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

問題概述

Redis(十四)雙寫一致性工程案例,Java,redis,數(shù)據(jù)庫,緩存

canal

https://github.com/alibaba/canal

功能

  1. 數(shù)據(jù)庫鏡像
  2. 數(shù)據(jù)庫實時備份
  3. 索引構建和實時維護(拆分異構索引、倒排索引等)
  4. 業(yè)務 cache 刷新
  5. 帶業(yè)務邏輯的增量數(shù)據(jù)處理
    Redis(十四)雙寫一致性工程案例,Java,redis,數(shù)據(jù)庫,緩存
    傳統(tǒng)mysql主從復制原理
    MySQL的主從復制將經(jīng)過如下步驟:
  6. 當 master 主服務器上的數(shù)據(jù)發(fā)生改變時,則將其改變寫入二進制事件日志文件中;
  7. salve 從服務器會在一定時間間隔內對 master 主服務器上的二進制日志進行探測,探測其是否發(fā)生過改變,
    如果探測到 master 主服務器的二進制事件日志發(fā)生了改變,則開始一個 I/O Thread 請求 master 二進制事件日志;
  8. 同時 master 主服務器為每個 I/O Thread 啟動一個dump Thread,用于向其發(fā)送二進制事件日志;
  9. slave 從服務器將接收到的二進制事件日志保存至自己本地的中繼日志文件中;
    Redis(十四)雙寫一致性工程案例,Java,redis,數(shù)據(jù)庫,緩存
    Canal原理’
    Redis(十四)雙寫一致性工程案例,Java,redis,數(shù)據(jù)庫,緩存

Redis(十四)雙寫一致性工程案例,Java,redis,數(shù)據(jù)庫,緩存

安裝部署

https://github.com/alibaba/canal/releases/tag/canal-1.1.6

mysql配置

# 查看mysql版本
SELECT VERSION();
# 查看是否開啟bin_log
SHOW VARIABLES LIKE 'log_bin';

mysql中my.ini配置
linux為my.cnf

# Linux 尋找my.cnf命令
find / -name my.cnf 
# my.ini
log-bin=mysql-bin #開啟 binlog
binlog-format=ROW #選擇 ROW 模式
server_id=1    #配置MySQL replaction需要定義,不要和canal的 slaveId重復
  • ROW模式 除了記錄sql語句之外,還會記錄每個字段的變化情況,能夠清楚的記錄每行數(shù)據(jù)的變化歷史,但會占用較多的空間。
  • STATEMENT模式只記錄了sql語句,但是沒有記錄上下文信息,在進行數(shù)據(jù)恢復的時候可能會導致數(shù)據(jù)的丟失情況;
  • MIX模式比較靈活的記錄,理論上說當遇到了表結構變更的時候,就會記錄為statement模式。當遇到了數(shù)據(jù)更新或者刪除情況下就會變?yōu)閞ow模式;
    Redis(十四)雙寫一致性工程案例,Java,redis,數(shù)據(jù)庫,緩存
    重啟mysql

授權canal連接mysql賬號

# 查詢現(xiàn)有賬戶
SELECT * FROM mysql.`user`

新建canal用戶

# 如果存在名為 'canal' 的用戶,且允許從任何主機 '%' 登錄,則刪除該用戶。
DROP USER IF EXISTS 'canal'@'%';
# 創(chuàng)建一個名為 'canal' 的用戶,允許從任何主機 '%' 登錄,密碼為 'canal'。
CREATE USER 'canal'@'%' IDENTIFIED BY 'canal';  
# 賦予 'canal' 用戶在所有數(shù)據(jù)庫中的所有表的全部權限,并使用密碼 'canal'。
GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' IDENTIFIED BY 'canal';
# 刷新 MySQL 的權限表,使修改后的權限立即生效。
FLUSH PRIVILEGES;
 
SELECT * FROM mysql.user;

canal服務端

下載
https://github.com/alibaba/canal/releases/tag/canal-1.1.6
解壓.tar.gz配置
修改conf/example/instance.properties
配置mysql主機ip
Redis(十四)雙寫一致性工程案例,Java,redis,數(shù)據(jù)庫,緩存
配置mysql賬號密碼
Redis(十四)雙寫一致性工程案例,Java,redis,數(shù)據(jù)庫,緩存
啟動
啟動腳本bin/startup.sh
前提:安裝好java8環(huán)境
./start.sh
查看日志
server日志:logs/canal.log
樣例日志:logs/example.log

canal客戶端(Java程序)

# 選個數(shù)據(jù)庫,以你自己為主,本例bigdata,按照下面建表
CREATE TABLE `t_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `userName` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4

pom引入canal

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.atguigu.canal</groupId>
    <artifactId>canal_demo02</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.14</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
        <mysql.version>5.1.47</mysql.version>
        <druid.version>1.1.16</druid.version>
        <mapper.version>4.1.5</mapper.version>
        <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
    </properties>

    <dependencies>
        <!--canal-->
        <dependency>
            <groupId>com.alibaba.otter</groupId>
            <artifactId>canal.client</artifactId>
            <version>1.1.0</version>
        </dependency>
        <!--SpringBoot通用依賴模塊-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--swagger2-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!--SpringBoot與Redis整合依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!--SpringBoot與AOP-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
        <!--Mysql數(shù)據(jù)庫驅動-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!--SpringBoot集成druid連接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
        </dependency>
        <!--mybatis和springboot整合-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.spring.boot.version}</version>
        </dependency>
        <!--通用基礎配置junit/devtools/test/log4j/lombok/hutool-->
        <!--hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.2.3</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <optional>true</optional>
        </dependency>
        <!--persistence-->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0.2</version>
        </dependency>
        <!--通用Mapper-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>${mapper.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.8.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

YML

# ========================alibaba.druid=====================
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/上面的數(shù)據(jù)庫?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.druid.test-while-idle=false

主啟動
業(yè)務類

public class RedisUtils
{
    public static final String  REDIS_IP_ADDR = "192.168.1.1";
    public static final String  REDIS_pwd = "";
    public static JedisPool jedisPool;

    static {
        JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(5);
        jedisPoolConfig.setMaxIdle(5);
        jedisPool=new JedisPool(jedisPoolConfig,REDIS_IP_ADDR,6379,30000,REDIS_pwd);
    }

    public static Jedis getJedis() throws Exception {
        if(null!=jedisPool){
            return jedisPool.getResource();
        }
        throw new Exception("Jedispool fail");
    }

}

https://github.com/alibaba/canal/wiki/ClientExample

CANAL_IP_ADDR:CANAL服務端ip地址
Canal默認端口11111

public class RedisCanalClientExample
{
    public static final Integer _60SECONDS = 60;
    public static final String  CANAL_IP_ADDR = "192.168.111.185";

    private static void redisInsert(List<Column> columns)
    {
        JSONObject jsonObject = new JSONObject();
        for (Column column : columns)
        {
            System.out.println(column.getName() + " : " + column.getValue() + "    update=" + column.getUpdated());
            jsonObject.put(column.getName(),column.getValue());
        }
        if(columns.size() > 0)
        {
            try(Jedis jedis = RedisUtils.getJedis())
            {
                jedis.set(columns.get(0).getValue(),jsonObject.toJSONString());
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }


    private static void redisDelete(List<Column> columns)
    {
        JSONObject jsonObject = new JSONObject();
        for (Column column : columns)
        {
            jsonObject.put(column.getName(),column.getValue());
        }
        if(columns.size() > 0)
        {
            try(Jedis jedis = RedisUtils.getJedis())
            {
                jedis.del(columns.get(0).getValue());
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    private static void redisUpdate(List<Column> columns)
    {
        JSONObject jsonObject = new JSONObject();
        for (Column column : columns)
        {
            System.out.println(column.getName() + " : " + column.getValue() + "    update=" + column.getUpdated());
            jsonObject.put(column.getName(),column.getValue());
        }
        if(columns.size() > 0)
        {
            try(Jedis jedis = RedisUtils.getJedis())
            {
                jedis.set(columns.get(0).getValue(),jsonObject.toJSONString());
                System.out.println("---------update after: "+jedis.get(columns.get(0).getValue()));
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    public static void printEntry(List<Entry> entrys) {
        for (Entry entry : entrys) {
            if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN || entry.getEntryType() == EntryType.TRANSACTIONEND) {
                continue;
            }

            RowChange rowChage = null;
            try {
                //獲取變更的row數(shù)據(jù)
                rowChage = RowChange.parseFrom(entry.getStoreValue());
            } catch (Exception e) {
                throw new RuntimeException("ERROR ## parser of eromanga-event has an error,data:" + entry.toString(),e);
            }
            //獲取變動類型
            EventType eventType = rowChage.getEventType();
            System.out.println(String.format("================&gt; binlog[%s:%s] , name[%s,%s] , eventType : %s",
                    entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(),
                    entry.getHeader().getSchemaName(), entry.getHeader().getTableName(), eventType));

            for (RowData rowData : rowChage.getRowDatasList()) {
                if (eventType == EventType.INSERT) {
                    redisInsert(rowData.getAfterColumnsList());
                } else if (eventType == EventType.DELETE) {
                    redisDelete(rowData.getBeforeColumnsList());
                } else {//EventType.UPDATE
                    redisUpdate(rowData.getAfterColumnsList());
                }
            }
        }
    }


    public static void main(String[] args)
    {
        System.out.println("---------O(∩_∩)O哈哈~ initCanal() main方法-----------");

        //=================================
        // 創(chuàng)建鏈接canal服務端
        CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress(CANAL_IP_ADDR,
                11111), "example", "", "");
        int batchSize = 1000;
        //空閑空轉計數(shù)器
        int emptyCount = 0;
        System.out.println("---------------------canal init OK,開始監(jiān)聽mysql變化------");
        try {
            connector.connect();
            //connector.subscribe(".*\\..*");
            connector.subscribe("bigdata.t_user");
            connector.rollback();
            int totalEmptyCount = 10 * _60SECONDS;
            while (emptyCount < totalEmptyCount) {
                System.out.println("我是canal,每秒一次正在監(jiān)聽:"+ UUID.randomUUID().toString());
                Message message = connector.getWithoutAck(batchSize); // 獲取指定數(shù)量的數(shù)據(jù)
                long batchId = message.getId();
                int size = message.getEntries().size();
                if (batchId == -1 || size == 0) {
                    emptyCount++;
                    try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
                } else {
                    //計數(shù)器重新置零
                    emptyCount = 0;
                    printEntry(message.getEntries());
                }
                connector.ack(batchId); // 提交確認
                // connector.rollback(batchId); // 處理失敗, 回滾數(shù)據(jù)
            }
            System.out.println("已經(jīng)監(jiān)聽了"+totalEmptyCount+"秒,無任何消息,請重啟重試......");
        } finally {
            connector.disconnect();
        }
    }
}

connector.subscribe配置過濾
Redis(十四)雙寫一致性工程案例,Java,redis,數(shù)據(jù)庫,緩存
try-with-resources
Redis(十四)雙寫一致性工程案例,Java,redis,數(shù)據(jù)庫,緩存文章來源地址http://www.zghlxwxcb.cn/news/detail-832833.html

到了這里,關于Redis(十四)雙寫一致性工程案例的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Redis緩存雙寫一致性

    Redis緩存雙寫一致性

    如果redis中有數(shù)據(jù):需要和數(shù)據(jù)庫中的值相同 如果redis中無數(shù)據(jù):數(shù)據(jù)庫中的值要是最新值,且準備回寫redis 緩存按照操作來分,可細分為兩種: 只讀緩存和讀寫緩存 只讀緩存很簡單:就是Redis只做查詢,有就是有,沒有就是沒有,不會再進一步訪問MySQL,不再需要會寫機制

    2023年04月17日
    瀏覽(18)
  • Redis緩存(雙寫一致性問題)

    Redis緩存(雙寫一致性問題)

    前言 : 什么是緩存? 緩存就像自行車,越野車的避震器 舉個例子:越野車,山地自行車,都擁有\(zhòng)\\"避震器\\\", 防止 車體加速后因慣性,在酷似\\\"U\\\"字母的地形上飛躍,硬著陸導致的 損害 ,像個彈簧一樣; 同樣,實際開發(fā)中,系統(tǒng)也需要\\\"避震器\\\",防止過高的數(shù)據(jù)訪問猛沖系統(tǒng),導致其操作線程無法

    2024年02月02日
    瀏覽(22)
  • Redis---緩存雙寫一致性

    Redis---緩存雙寫一致性

    目錄 一、什么是緩存雙寫一致性呢? ?1.1 雙檢加鎖機制 ?二、數(shù)據(jù)庫和緩存一致性的更新策略 2.1、先更新數(shù)據(jù)庫,后更新緩存 ?2.2 、先更新緩存,后更新數(shù)據(jù)庫 ?2.3、先刪除緩存,在更新數(shù)據(jù)庫 延時雙刪的策略: ?2.4.先更新數(shù)據(jù)庫,在刪除緩存(常用) 2.5、實際中是不可

    2024年02月15日
    瀏覽(26)
  • Redis高級系列-緩存雙寫一致性

    Redis高級系列-緩存雙寫一致性

    Redis緩存雙寫一致性是指在更新數(shù)據(jù)庫數(shù)據(jù)后,同時更新緩存數(shù)據(jù)以保持數(shù)據(jù)一致性的策略,總的來說,就是 寫入redis 和 寫入數(shù)據(jù)庫 的數(shù)據(jù)要保持一致 2.1 Cache Aside Pattern(旁路緩存模式) 旁路緩存模式,字面意思理解:緩存是旁路,緩存相對與應用程序和數(shù)據(jù)庫是旁路,應用

    2024年01月20日
    瀏覽(26)
  • 【Redis】聊一下緩存雙寫一致性

    【Redis】聊一下緩存雙寫一致性

    緩存雖然可以提高查詢數(shù)據(jù)的的性能,但是在緩存和數(shù)據(jù) 進行更新的時候 其實會出現(xiàn)數(shù)據(jù)不一致現(xiàn)象,而這個不一致其實可能會給業(yè)務來帶一定影響。無論是Redis 分布式緩存還是其他的緩存機制都面臨這樣的問題。 數(shù)據(jù)一致性 緩存中有數(shù)據(jù),那么緩存的數(shù)據(jù)和數(shù)據(jù)庫的數(shù)據(jù)

    2024年02月06日
    瀏覽(25)
  • Redis緩存雙寫一致性之更新策略

    Redis緩存雙寫一致性之更新策略

    你只要用緩存,就可能會涉及到redis緩存與數(shù)據(jù)庫雙存儲雙寫,你只要是雙寫,就一定會有數(shù)據(jù)一致性的問題,那么你如何解決一致性問題? 雙寫一致性,你先動緩存redis還是數(shù)據(jù)庫mysql哪一個?why? 延時雙刪你做過嗎?會有哪些問題? 有這么一種情況,微服務查詢redis無m

    2024年02月05日
    瀏覽(28)
  • Redis與MySQL雙寫一致性如何保證

    Redis與MySQL雙寫一致性如何保證

    前言 在分布式系統(tǒng)中,數(shù)據(jù)一致性是一個重要的問題。當我們使用Redis和MySQL這兩種不同的數(shù)據(jù)庫時,如何保證它們之間的雙寫一致性是一個需要解決的難題。本文將探討Redis與MySQL雙寫一致性的保證方法。 什么是雙寫一致性? 指的是當我們更新了數(shù)據(jù)庫的數(shù)據(jù)之后redis中的數(shù)

    2024年02月09日
    瀏覽(28)
  • Redis緩存問題:穿透,擊穿,雪崩,雙寫一致性等

    Redis緩存問題:穿透,擊穿,雪崩,雙寫一致性等

    在高并發(fā)場景下,數(shù)據(jù)庫往往是最薄弱的環(huán)節(jié),我們通常選擇使用 redis 來進行緩存,以起到緩沖作用,來降低數(shù)據(jù)庫的壓力,但是一旦緩存出現(xiàn)問題,也會導致數(shù)據(jù)庫瞬間壓力過大甚至崩潰,從而導致整個系統(tǒng)崩潰.今天就聊聊常見的 redis 緩存問題. 緩存擊穿 緩存擊穿一般指redis中的一

    2024年04月27日
    瀏覽(31)
  • 如何保證redis與db的雙寫一致性

    ? ? 如何保證redis與db的雙寫一致性?這是一個十分熱門的面試話題。 如何理解“一致性”這個概念?“事務”中“一致性”的定義是: 事務執(zhí)行前后,數(shù)據(jù)從一個合法性狀態(tài)變換到另外一個合法性狀態(tài)。? 比喻說,更新前:redis中記錄的是100,db中記錄的也是100。更新后:?

    2024年02月07日
    瀏覽(25)
  • [優(yōu)雅的面試]MySQL與Redis雙寫一致性方案

    [優(yōu)雅的面試]MySQL與Redis雙寫一致性方案

    前言 由于緩存的高并發(fā)和高性能已經(jīng)在各種項目中被廣泛使用,在讀取緩存這方面基本都是一致的,大概都是按照下圖的流程進行操作: 但是在更新緩存方面,是更新完數(shù)據(jù)庫再更新緩存還是直接刪除緩存呢?又或者是先刪除緩存再更新數(shù)據(jù)庫?在這一點上就值得探討了。

    2024年01月21日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包