MySQL8 read-write separation cluster

Table of contents

1. MySQL read and write separation principle

2. Build a MySQL read-write separation cluster 

Before MySQL8.0

1. Download the MyCat installation package

2. Configure schema.xml and server.xml respectively

3. Start MyCat

4. MyCat implements MySQL reading and writing separation

After MySQL8.0

1. When connecting to MySQL, only the url configuration changes

2. Only the transaction of the display setting method is read-only (readOnly = true), and it will go from the slave (read) library when it is executed alone.


1. MySQL read and write separation principle

In MySQL read-write separation: the master node is specially used for data modification operations ( 如create、update、insert、deleteetc.), writing on the main database, and then the main database 主从复制synchronizes the data changes binlogto all slave databases.

Then map all query operations to the slave database, so that 分摊读写的压力all requests do not need to be concentrated on the master database, so that MySQL's concurrent processing capabilities can be greatly improved.

"Before MySQL 8.0:" This process requires a middleware (such as MyCat, Sharding-JDBCetc.) to identify and parse all requests from the client, map all write operations to the master node, and read operations are transferred to the slave database.

"After MySQL 8.0:"MySQL自身已支持读写分离 (Supported 一主多从reading and writing separation 多主多从still need to introduce middleware implementation)

"Reading and writing separation of one master and multiple slaves:"

注意:After MySQL 8.0, 一主多从the separation of reading and writing does not depend on middleware.

2. Build a MySQL read-write separation cluster 

Before MySQL8.0

1. Download the MyCat installation package

Download MyCat: http://dl.mycat.org.cn 

2. Configure schema.xmlandserver.xml

I configure the virtual library here to map to the real library meet0and1-schemaon the master and slave nodes.meet0and1


<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    <!-- 定义MyCat的虚拟逻辑库,dataNode:映射真实数据节点  -->   
    <schema name="meet0and1-schema" checkSQLschema="false" sqlMaxLimit="800" dataNode="meet0and1Node" />
    <!-- 定义MyCat的数据节点,name必须和dataNode值一致,dataHost映射真实主机,database映射真实的库 -->
    <dataNode name="meet0and1Node" dataHost="meet0and1Host" database="meet0and1" />
    
    <!-- 配置数据主机,name必须和dataHost一致 -->
    <dataHost name="meet0and1Host" maxCon="1000" minCon="10" balance="1"
              writeType="0" dbType="mysql" dbDriver="native" switchType="-1"  slaveThreshold="100">
        <!--心跳检测-->
        <heartbeat>select user()</heartbeat>
        <!--主节点(写)-->
        <writeHost host="hostM1" url="192.168.31.161:3306" user="root" password="123456">
            <!--从节点(读)-->
            <readHost host="hostS1" url="192.168.31.162:3306" user="root" password="123456" />
        </writeHost>
    </dataHost>
</mycat:schema>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
    <!-- 这里配置的都是一些系统属性-->
    <system>
      <!-- 默认的sql解析方式 -->
      <property name="defaultSqlParser">druidparser</property>
      <property name="charset">utf8mb4</property>
    </system>
    <!-- 配置登录mycat的用户信息 -->
    <user name="root">
      <property name="password">123456</property>
      <!-- 该用户可以操作哪个逻辑库 -->
      <property name="schemas">meet0and1-schema</property>
    </user>
</mycat:server>

3. Start MyCat

In the bin directory of mycat, start MyCat

# 以前台窗口启动
./mycat console
# 以后台守护进程启动
./mycat start
./mycat status
./mycat stop
./mycat restart

4. MyCat implements MySQL reading and writing separation

Modify properties to connect to MySQL configuration

# MyCat的server.xml中配置的用户和密码
spring.datasource.username=root
spring.datasource.password=123456
# MyCat服务的端口8066,meet0and1-schema:MyCat中配置映射到meet0and1的虚拟库
spring.datasource.url=jdbc:mysql://192.168.31.161:8066/meet0and1-schema?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

"Note:" Transactions in Spring support propagation. In order to avoid performing an update operation in a query, MyCat transfers the connection request to the slave database, resulting in inconsistent master-slave data. ThereforeMyCat会开启了事务的连接请求都转到master主库

For example, in the following findAllmethod, the query operation should go through the slave library. However, since transactions are enabled on the class, if the transaction propagation attribute on the method is not set to SUPPORTS, executing this method will go through the master library.

@Service
@Transactional(rollbackFor = Exception.class)
public class SysUserService {

    @Autowired
    private SysUserDao sysUserDao;

    /**
     * Propagation.SUPPORTS:支持事务的传播
     * 有事务则融入:如其他含有事务的方法调用这个方法时,融入调用方的事务
     * 没有则不开启事务:它自身的方法不开启事务,且这里覆盖了类上配置的事务
     * (方法上的事务优先级大于类上开启的事务)
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    public List<SysUser> findAll() {
        return sysUserDao.findAll();
    }

    /**
     * 执行写操作,会走master主库
     */
    public void save(SysUser sysUser) {
        sysUserDao.save(sysUser);
    }

}

After MySQL8.0

The separation of reading and writing after MySQL 8.0 一主多从no longer relies on any middleware

1. When connecting to MySQL, only the url configuration changes

# 语法:默认配置的第一个节点为主(写)库,后面的都为从(读)库
jdbc:mysql:replication://主(写)库,从(读)库1,从(读)库2,从(读)库N/库名

Example:

spring.datasource.url=jdbc:mysql:replication://192.168.31.161:3306,192.168.31.162:3306/meet0and1?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8

2. Only the transaction of the display setting method is read-only ( readOnly = true), and it will go from the slave (read) library when it is executed alone.

Only query operations whose transactions are read-only are executed 从(读)库!

为保证主从节点数据的一致性: When other servicemethods are called, no matter whether they contain transactions or not, even if they do not contain update operations (insert/update/delete), the following methods will be used 主(写)库, such as the following

@Service
public class SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 这里只有设置事务为只读,且单独执行该方法时才走从(读)库
     */
    @Transactional(readOnly = true)
    public List<SysUser> findAll(){
        return sysUserMapper.findAll();
    }

    @Transactional
    public void hasTranFind(){
        // 走主(写)库
        findAll().forEach(System.out::println);
    }

    public void notTranFind(){
        // 走主(写)库
        findAll().forEach(System.out::println);
    }

    public void notTranSave(SysUser sysUser){
        // 走主(写)库
        findAll().forEach(System.out::println);
        sysUserMapper.save(sysUser);
    }

    /**
     * 该方法执行会报错:Connection is read-only. Queries leading to data modification are not allowed
     * (设置只读的事务方法中,不能有非查询操作)
     */
    @Transactional(readOnly = true)
    public List<SysUser> findAll2(SysUser sysUser){
        sysUserMapper.save(sysUser);
        return sysUserMapper.findAll();
    }

}

Precautions

The current community and project maintenance of MyCat is not very friendly. Although MySQL supports it after 8.0一主多从的读写分离

However, in large-scale projects with extremely high concurrency 分库分表, it is recommended to implement "Sharding-JDBC"读写分离 for functions such as and分布式主键

Guess you like

Origin blog.csdn.net/Clearlove_S7/article/details/132355948