• Sharding-JDBC(五)- Sharding-JDBC读写分离


    一、理解读写分离

    面对日益增加的系统访问量,数据库的吞吐量面临着巨大瓶颈。 对于同一时刻有大量并发读操作和较少写操作类型的应用系统来说,将数据库拆分为主库和从库,主库负责处理事务性的增删改操作,从库负责处理查询操作,能够有效的避免由数据更新导致的行锁,使得整个系统的查询性能得到极大的改善。

    在这里插入图片描述

    通过一主多从的配置方式,可以将查询请求均匀的分散到多个数据副本,能够进一步的提升系统的处理能力。 使用多主多从的方式,不但能够提升系统的吞吐量,还能够提升系统的可用性,可以达到在任何一个数据库宕机,甚至磁盘物理损坏的情况下仍然不影响系统的正常运行。

    在这里插入图片描述

    读写分离的数据节点中的数据内容是一致的,而水平分片的每个数据节点的数据内容却并不相同。将水平分片和读写分离联合使用,能够更加有效的提升系统的性能。

    Sharding-JDBC读写分离则是根据SQL语义的分析,将读操作和写操作分别路由至主库与从库。它提供透明化读写分离,让使用方尽量像使用一个数据库一样使用主从数据库集群。

    在这里插入图片描述

    Sharding-JDBC提供一主多从的读写分离配置,可独立使用,也可配合分库分表使用,同一线程且同一数据库连接 内,如有写入操作,以后的读操作均从主库读取,用于保证数据一致性。Sharding-JDBC不提供主从数据库的数据同步功能,需要采用其他机制支持。

    在这里插入图片描述

    接下来,咱们对上面例子中user_db进行读写分离实现。为了实现Sharding-JDBC的读写分离,首先,要进行 mysql的主从同步配置。

    二、mysql主从同步(windows)

    1. 新增mysql实例

    复制原有mysql如:D:\mysql-5.7.25(作为主库) -> D:\mysql-5.7.25-s1(作为从库),并修改以下从库的my.ini:

    [mysqld] #设置3307端口
    port = 3307
    #设置mysql的安装目录
    basedir=D:\mysql‐5.7.25‐s1
    #设置mysql数据库的数据的存放目录
    datadir=D:\mysql‐5.7.25‐s1\data

    然后将从库安装为windows服务,注意配置文件位置:

    D:\mysql‐5.7.25‐s1\bin>mysqld install mysqls1 ‐‐defaults‐file=“D:\mysql‐5.7.25‐s1\my.ini”

    由于从库是从主库复制过来的,因此里面的数据完全一致,可使用原来的账号、密码登录。

    2. 修改主、从库的配置文件(my.ini)

    主库:

    [mysqld]
    #开启日志
    log‐bin = mysql‐bin
    #设置服务id,主从不能一致
    server‐id = 1
    #设置需要同步的数据库
    binlog‐do‐db=user_db
    #屏蔽系统库同步
    binlog‐ignore‐db=mysql
    binlog‐ignore‐db=information_schema
    binlog‐ignore‐db=performance_schema

    从库:

    [mysqld]
    #开启日志
    log‐bin = mysql‐bin
    #设置服务id,主从不能一致
    server‐id = 2
    #设置需要同步的数据库
    replicate_wild_do_table=user_db.%
    #屏蔽系统库同步
    replicate_wild_ignore_table=mysql.%
    replicate_wild_ignore_table=information_schema.%
    replicate_wild_ignore_table=performance_schema.%

    重启主库和从库:

    net start [主库服务名]
    net start [从库服务名mysqls1]

    请注意,主从MySQL下的数据(data)目录下有个文件auto.cnf,文件中定义了uuid,要保证主从数据库实例的 uuid不一样,建议直接删除掉,重启服务后将会重新生成。

    3. 授权主从复制专用账号

    #切换至主库bin目录,登录主库
    mysql ‐h localhost ‐uroot ‐p
    #授权主备复制专用账号
    GRANT REPLICATION SLAVE ON . TO ‘db_sync’@‘%’ IDENTIFIED BY ‘db_sync’;
    #刷新权限 FLUSH PRIVILEGES;
    #确认位点 记录下文件名以及位点
    show master status;

    在这里插入图片描述

    4. 设置从库向主库同步数据、并检查链路

    #切换至从库bin目录,登录从库
    mysql ‐h localhost ‐P3307 ‐uroot ‐p
    #先停止同步 STOP SLAVE;
    #修改从库指向到主库,使用上一步记录的文件名以及位点
    CHANGE MASTER TO
    master_host = ‘localhost’,
    master_user = ‘db_sync’,
    master_password = ‘db_sync’,
    master_log_file = ‘mysql‐bin.000002’,
    master_log_pos = 154;
    #启动同步 START SLAVE;
    #查看从库状态Slave_IO_Runing和Slave_SQL_Runing都为Yes说明同步成功,如果不为Yes,请检查error_log,然后 排查相关异常。
    show slave status\G
    #注意 如果之前此备库已有主库指向 需要先执行以下命令清空
    STOP SLAVE IO_THREAD FOR CHANNEL ‘’;
    reset slave all;

    最后测试在主库修改数据库,看从库是否能够同步成功。

    三、实现sharding-jdbc读写分离

    (1) 在Sharding-JDBC规则中修改

    #sharding-jdbc分片规则配置
    #数据源
    spring.shardingsphere.datasource.names = m0,m1,m2,s0
    ...
    spring.shardingsphere.datasource.s0.type = com.alibaba.druid.pool.DruidDataSource
    spring.shardingsphere.datasource.s0.driver-class-name = com.mysql.jdbc.Driver
    spring.shardingsphere.datasource.s0.url = jdbc:mysql://localhost:3307/user_db?useUnicode=true
    spring.shardingsphere.datasource.s0.username = root
    spring.shardingsphere.datasource.s0.password = root
    ...
    # 主库从库逻辑数据源定义 ds0为user_db 
    spring.shardingsphere.sharding.master‐slave‐rules.ds0.master‐data‐source‐name=m0
    spring.shardingsphere.sharding.master‐slave‐rules.ds0.slave‐data‐source‐names=s0
    
    # t_user分表策略,固定分配至ds0的t_user真实表 
    spring.shardingsphere.sharding.tables.t_user.actual‐data‐nodes = ds0.t_user
    ....
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    (2) 测试

    执行testInsertUser单元测试:

    @Test
    public void testInsertUser(){
        for (int i = 0 ; i < 2; i++){
            Long id = i + 1L;
            userDao.insertUser(id,"姓名"+ id );
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    通过日志可以看出,所有写操作落入m0数据源。

    执行testSelectUserbyIds单元测试:

    @Test
    public void testSelectUserInfobyIds(){
         List<Long> userIds = new ArrayList<>();
         userIds.add(1L);
         userIds.add(2L);
         List<Map> users = userDao.selectUserInfobyIds(userIds);
         System.out.println(users);
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    通过日志可以看出,所有写操作落入s0数据源,达到目标。

  • 相关阅读:
    微信公众号扫码登录(一)—— 获取微信公众号二维码
    音视频+AI,中关村科金助力某银行探索发展新路径 | 案例研究
    Java工程师只要掌握这些知识点,就能给面试官一个满意的答案,挑战高薪
    多线程&并发篇---第十二篇
    力扣174. 寻找二叉搜索树中的目标节点(java,二叉搜索树的性质的运用)
    websocket 请求头报错 Provisional headers are shown 的解决方法
    javascript二维数组(19)不要键名只保留值的算法
    4.爬虫之Scrapy框使用2
    xml的语法
    【整数正序按指定位数分解为2个数】2023-9-19
  • 原文地址:https://blog.csdn.net/qq_36602071/article/details/126824150