首页 > 数据库 >MySQL 读写分离

MySQL 读写分离

时间:2024-10-12 13:50:11浏览次数:3  
标签:主库 jdbc 数据源 读写 分离 MySQL 操作 从库

优质博文:IT-BLOG-CN

一、背景

随着机票业务不断增长,订单库的读性能遇到了挑战,因此对订单库进行读写分离操作。主要目的是提高数据库的并发性能和可扩展性。当系统的所有写操作效率尚可,读数据请求效率较低时,比如之前订单表存放了几千万条数据,且查询订单信息需要关联十几个字表,每个字表的数据超亿条。查询超过设置的慢SQL查询时间3s。以下是一些具体原因和好处:读写分离的功能基于主从复制
1、性能提升:
【1】读写负载分担:通过将读操作和写操作分离,可以将写操作集中在主库Master上,而将读操作分散到多个从库Slave上。这可以显著减少主库的负载,提高整体系统的响应速度。
【2】并发处理能力:读写分离可以利用多个从库来处理并发读请求,从而提高系统的并发处理能力。

2、可扩展性:
【1】横向扩展:通过增加从库的数量,可以轻松地扩展系统的读处理能力,而不需要对主库进行复杂的扩展。
【2】负载均衡:可以使用负载均衡技术将读请求分发到不同的从库上,从而实现更好的资源利用和性能优化。

3、数据安全性和容错性:
【1】数据备份:从库可以用作数据备份的一部分,提供数据冗余和容错能力。如果主库发生故障,从库可以迅速接管读操作,甚至在必要时提升为新的主库。
【2】灾难恢复:在灾难恢复场景中,从库可以作为主库的备份,确保数据的安全性和可恢复性。

4、缓存和索引优化: 从库可以针对特定的读操作进行优化,如创建特定的索引或缓存策略,而不影响主库的写操作性能。

扩展:慢查询超时时间配置:在MySQL的配置文件(通常是my.cnfmy.ini)中设置long_query_time。在[mysqld]部分添加或修改以下行:

[mysqld]
slow_query_log = 1
slow_query_log_file = /path/to/your/slow_query.log
long_query_time = 2

二、主从读写分离

主从复制完成后,我们还需要实现读写分离,master负责写入数据,两台slave负责读取数据。我们项目因为数据太大,所以使用Sharding-JDBC进行了分表分库。这里就说下通过Sharding-JDBC怎么实现数据读写分离的。

【1】引入依赖: 项目中引入Sharding-JDBC的依赖。

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core</artifactId>
    <version>5.x.x</version> <!-- 请使用最新版本 -->
</dependency>

【2】配置数据源: 需要配置多个数据源,通常包括一个主库Master``和一个或多个从库Slave。以下是一个简单的Spring Boot`配置示例:

import org.apache.shardingsphere.driver.api.yaml.YamlShardingSphereDataSourceFactory;
import javax.sql.DataSource;
import java.io.File;

@Configuration
public class DataSourceConfig {

    @Bean
    public DataSource dataSource() throws Exception {
        File yamlFile = new File("path/to/sharding-jdbc-config.yaml");
        return YamlShardingSphereDataSourceFactory.createDataSource(yamlFile);
    }
}

【3】配置YAML文件:sharding-jdbc-config.yaml文件中,配置读写分离的相关信息。以下是一个示例配置:

dataSources:
  master:
    type: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: jdbc:mysql://localhost:3306/master_db
    username: root
    password: root
  slave0:
    type: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: jdbc:mysql://localhost:3306/slave_db0
    username: root
    password: root
  slave1:
    type: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: jdbc:mysql://localhost:3306/slave_db1
    username: root
    password: root

rules: # 用于定义数据分片、读写分离等规则。在这个例子中,我们定义了一个读写分离的规则。
  - !READWRITE_SPLITTING # 是一个 YAML 类型标签,用于指示接下来的配置是一个读写分离规则。
    dataSources: # 是一个键,表示接下来要定义的是数据源的配置。在这个例子中,我们定义了一个名为 pr_ds 的逻辑数据源。
      pr_ds: # pr_ds 是逻辑数据源的名称。你可以在应用程序中使用这个名称来引用这个读写分离的数据源。
        writeDataSourceName: master # 指定了用于写操作的主数据源。在这个例子中,主数据源的名称是 master。所有的写操作(例如 INSERT、UPDATE、DELETE)都会路由到这个数据源。
        readDataSourceNames: # 是一个列表,指定了用于读操作的从数据源。在这个例子中,有两个从数据源,分别是 slave0 和 slave1。所有的读操作(例如 SELECT)会根据负载均衡策略路由到这些从数据源。
          - slave0
          - slave1
        loadBalancerName: round_robin # loadBalancerName 指定了用于读操作的负载均衡策略。在这个例子中,负载均衡策略的名称是 round_robin,表示轮询策略。轮询策略会将读操作均匀地分布到多个从数据源上

loadBalancers:
  round_robin:
    type: ROUND_ROBIN

【4】使用Sharding-JDBC数据源: 使用配置好的Sharding-JDBC数据源。以下是一个简单的示例:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void performDatabaseOperations() {
        // 写操作会路由到主库
        jdbcTemplate.update("INSERT INTO my_table (name) VALUES (?)", "John Doe");

        // 读操作会路由到从库
        String name = jdbcTemplate.queryForObject("SELECT name FROM my_table WHERE id = ?", new Object[]{1}, String.class);
        System.out.println("Name: " + name);
    }
}

思考一:MySQL中的数据延迟同步的问题怎么解决?
我们主从使用的硬件配置都是一样的,MySQL使用的也是5.7版本,支持writeSet并行复制,但很多时间可能是网络延迟,就需要确保足够的宽带,以便数据传输,选择地理位置较近的服务器等等。重点是我们对数据实时性要求高的系统,会将主库写入的数据存入Redis缓存中,并给一个过期时间,过期时间的设计与主从复制延迟的时间成正比。

思考二:同一线程且同一数据库连接内,如果读写操作在一起,为了保证数据一致性,均从主库读取。

三、读非关系型数据库-技术选型

同步模式

适合查询数据的一致性和实时性高的系统。但业务代码侵入比较强,增大写操作的耗时,影响系统的写操作的QPS

异步模式

写入数据后,通过kafka异步建立查询数据,不影响业务流程,但需要考虑数据一致性问题。

binlog模式

这种方案也是我们使用的一套方案,还是借助自主研发的DRC服务,监听写数据库日志的方式建立查询数据,不影响主流程,代码无侵入。但需要注意数据一致性问题。

四、项目中的难点

消息幂等怎么保证?

消息幂等性在业务层保证一致,使用updateOrInsert方法,存在即更新,不存在则插入。那么在MongDB中也是一样的,使用条件更新Upsert,通过使用upsert选项,可以确保插入或更新操作是幂等的。如果文档不存在则插入,如果存在则更新。

db.collection.updateOne(
    { _id: documentId },
    { $set: { fieldName: newValue } },
    { upsert: true }
);

消费时序性怎么保证?

因为使用的是Kafka进行消息订阅消费,根据订单号进行分区消费,同一个订单分配至同一个分区,同一个分区是顺序消费的,从而保证消息的时序性。

消息一致性怎么保证?

搭建的数据同步系统DRC可以定时校验数据的一致性

查询数据存储为什么选 MongDB?

为了解决表数据量大查询缓慢的问题,不推荐选用关系型数据库了,内存数据库虽然性能非常高,比如Redis,但是不适合海量数据,太费钱了。所以重点考虑如下三种大数据存储模型:MongoDB/HBase/Elasticsearch

MongoDB:文档型数据库NoSQL,基于文档的存储,使用JSON(BSON)格式,丰富的查询语言,支持复杂的查询和聚合操作,水平扩展Sharding,最终一致性,支持多种一致性级别的配置。

标签:主库,jdbc,数据源,读写,分离,MySQL,操作,从库
From: https://blog.csdn.net/zhengzhaoyang122/article/details/142714320

相关文章

  • MySql.Data.dll官网下载
    原文链接:https://blog.csdn.net/weixin_30668887/article/details/96468519Mysql.Data.dll官网下载在项目开发中链接MySQL数据库经常要用到Mysql.Data.dll,网上虽然有很多,但是还是比较信赖官网的今天就从官网下载一次记录一下过程1.下载地址官网地址:https://www.mysql.com/2.......
  • ORCLE与MySQL的相互转化
    1.情景展示在实际开发中,不同的地方可能所需使用的数据库是不同的。这就要求,我们开发的程序需要兼容不同的数据库,放到程序里面就是:需要有不同类型的sqlMap文件。以既要兼容MySQL,也要兼容Oracle进行举例说明。2.准备工作第一步根据已经写好的一套sql进行复制,然后,在原有sql的......
  • cmakelist 源码生成so 文件 orthanc mysql
    cmakelist.txt#Orthanc-ALightweight,RESTfulDICOMStore#Copyright(C)2012-2016SebastienJodogne,MedicalPhysics#Department,UniversityHospitalofLiege,Belgium#Copyright(C)2017-2023OsimisS.A.,Belgium#Copyright(C)2024-2024Orthanc......
  • Starrocks表的数据库字段类型及与MySQL 的差异
    最近有用到Starrocks,实际使用中基本可以当作mysql来使用,但是数据库字段还是有所不同的。与MySQL相同或相似的基础类型数值类型TINYINT、SMALLINT、INT/INTEGER、BIGINT:在Starrocks和MySQL中的定义和用途基本相似。都是用于存储整数,范围也和MySQL中的对应类型相同,例如TI......
  • 泛微e-cology安装报错 MySQL初始化问题Table 'ecology.e9_para_xxx' doestn't exist
    在安装泛微e-cology9进行初始化数据库时出现如下报错Table 'ecology.e9_para_xxx'doestn'texist 明明是在初始化数据库  数据表不存在不是很正常==经过研究  发现泛微在初始化数据库时 会执行存储过程脚本  使用dbeaver可以看到 根据代码逻辑看  如......
  • MySQL数据备份
    MySQL数据备份是数据库管理员非常重要的工作之一。系统意外崩溃或者硬件的损坏都可能导致数据的丢失,因此MySQL管理员应该定期地备份数据,使得在意外情况发生时最大限度地减少损失。本节将介绍数据备份的3种方法。11.1.1 使用mysqldump命令备份数据mysqldump是MySQL提供的一个非......
  • mysql数据库服务器错误怎么回事
    MySQL数据库服务器错误可能由多种原因导致,这里列举一些常见的问题及其解决方法:服务未启动检查MySQL服务是否已经启动。在命令行中使用 netstartmysql (Windows)或 sudoservicemysqlstart (Linux)来尝试启动MySQL服务。配置文件错误确认my.cnf(Linux)或my.ini(Window......
  • 在Java程序中监听mysql的binlog
    目录1、背景2、mysql-binlog-connector-java简介3、准备工作1、验证数据库是否开启binlog2、开启数据库的binlog3、创建具有REPLICATIONSLAVE权限的用户4、事件类型eventType解释1、TABLE_MAP的注意事项2、获取操作的列名5、监听binlog的position1、从最新的binlog位置开始监......
  • MySQL 时间类型 DATE、DATETIME和TIMESTAMP
    1.DATE、DATETIME和TIMESTAMP表达的时间范围TypeRangeRemarkDATE'1000-01-01' to '9999-12-31'只有日期部分,没有时间部分DATETIME'1000-01-0100:00:00' to '9999-12-3123:59:59'时间格式为 YYYY-MM-DDhh:mm:ss,默认精确到秒TIMESTAMP '1970-01-0100:00:01......
  • 计算机毕业设计 基于Django的学生选课系统的设计与实现 Python+Django+Vue 前后端分离
    ......