mysql读写分离

之前做的某个项目中,mysql搭了集群,本来打算基于主从复制做读写分离的,因为不知道如何读写分离,于是改用了pxc集群,集群中的每个mysql都能读写,比较简单。最近比较空闲,调查一下mysql读写分离如何实现,特此记录。

前提: 搭建mysql主从复制集群,使得数据单向同步,可以参考mysql集群搭建与总结

这里在一台机器上通过docker映射不同的端口,搭建了mysql的主从复制集群(一主一从)

容器名端口
mysql-master3000
mysql-slave3001

方式一: 配置多个数据源

最简单的方式就是配置两个数据源,写入数据库的时候使用3000,从数据库读取的时候使用3001端口,这里以nodejs+sequelize为例,实现读写分离.

mysql-read-write.js

const Sequelize = require('sequelize')
//创建sequelize实例
const sequelize = new Sequelize('test', null, null, {
    dialect: 'mysql',
    replication: {
        read: [ 
            { host: '101.133.213.103', username: 'root', password: '123456', port: 3001 }
        ],
        write: { host: '101.133.213.103', username: 'root', password: '123456', port: 3000 }
    },
    pool: { // If you want to override the options used for the read/write pool you can do so here
        max: 20,
        idle: 5000
    },
})
//创建User Model,相当于建表
const User = sequelize.define('user', {
    userName: {
        type: Sequelize.STRING,
        allowNull: false, //是否允许为空
        primaryKey: true,
        comment: '用户名,唯一'
    },
}, {
    timestamps: false, //默认为true,自动生成`createdAt`和`updatedAt`字段
    freezeTableName: false //默认为false,表名自动是使用复数形式,如user->users
});
async function addUser({ userName }) {
    await User.create({
        userName,
    })
}
async function getUser({ userName }) {
    const result = await User.findOne({
        attributes: ['userName'],
        where: { userName }
    })
    return result.dataValues
}
(async () => {
    //创建user表
    await sequelize.sync({
        force: false  //如果表已经存在,则不会重新创建表
    })
    //写入一条数据
    await addUser({ userName: 'selenium' })
    //查询一条数据
    const user = await getUser({ userName: 'selenium' })
    console.log(user)
})()

通过上面的代码,我们往mysql-master插入了一条数据,并且从mysql-slave中读取了这条数据,但是真的是这样吗?

读写分离验证:

从库停止主从复制stop slave;

  1. 此时写入一条数据 ‘sakura’,只有mysql-master看得到这条数据,证明只写入到了mysql-master
    在这里插入图片描述
  2. 查询userName为 ‘sakura’ 的用户,发现查询不到,证明是从mysql-slave上读取的
    在这里插入图片描述

方式二:使用mycat中间件

配置多个数据源实现读写分离很简单,但是很明显,数据库与代码的耦合度很高。比较好的方式是使用mycat中间件。

它会拦截程序发送给mysql的sql语句,然后进行解析,将sql语句发送到合适的mysql中.

#下载mycat镜像
docker pull selenium39/mycat
#启动mycat容器
docker run -itd --privileged=true -p 8066:8066 -p 9066:9066 --name mycat selenium39/mycat
#进入容器,安装vim
docker exec -it mycat bash
apt-get udpate
apt-get install -y vim
#修改server.xml
vim /mycat/conf/server.xml

在这里插入图片描述
主要是两处修改:

  1. 将客户端的ip加入白名单,默认只能localhost访问
  2. 设置逻辑数据库的用户名和密码和数据库名称(虽然实际数据库有两个,但开发人员只能感知到一个逻辑数据库)
#修改schema.xml
vim /mycat/conf/schema.xml

schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="db_node">
        </schema>
        <dataNode name="db_node" dataHost="db_host" database="test" />
        <dataHost name="db_host" maxCon="1000" minCon="10" balance="3"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="101.133.213.103:3000" user="root"
                                   password="123456">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS2" url="101.133.213.103:3001" user="root" password="123456" />
                </writeHost>
                <!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
        </dataHost>
</mycat:schema>

主要是定义真实的读数据库和写数据库,并与逻辑数据库相关联

注意这里的balance指定的是 3
在这里插入图片描述

配置完成后,重启mycat容器,就可以通过连接逻辑数据库,进行业务开发,而mycat则会将自动的将读写分发到不同的数据库,实现读写分离.

//代码示例
//创建sequelize实例
const config = {
    host: '101.133.213.103',
    dialect: 'mysql',
    port: 8066
}
const sequelize = new Sequelize('TESTDB', 'root', '123456',config )

方式三:使用sharding-proxy中间件

以后再写🥰

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Selenium399

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值