前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据库的双机热备与读写分离

数据库的双机热备与读写分离

作者头像
姜同学
发布2022-10-27 16:18:05
7870
发布2022-10-27 16:18:05
举报
文章被收录于专栏:姜同学姜同学

三范式和反三范式

代码语言:javascript
复制
第一范式:所以字段不可再分(关系型数据库天生支持)
第二范式:所有非主键字段必须完全依赖主键字段,不能
出现部分依赖。
第三范式:在二范式的基础上消除传递依赖
互联网初期,没有什么高并发的概念,而且硬件非常昂贵
所以在数据库的设计上几乎都是选取时间换空间的三范式
表结构以及使用单机数据库。

但是时代在进步,社会在发展,高并发和分布式的概念也越来越火热,单机版的数据库已经不能满足如今的互联网,所以就有了mysql的读写分离和主从复制。

mysql主从复制的原理

代码语言:javascript
复制
#当前mysql在集群中的编号不能重复
server-id=
#开启mysql binlog日志
log-bin=mysql-log

在mysql的配置文件中添加上面两行配置(window系统为mysql数据存储路径下的my.in文件,linux系统在 etc 里面的my.cnf文件)。配置完成之后,主节点就开启binlog日志,在从节点的配置中只需要指定从节点在集群中的编号即可,在从节点中会开前io和sql两个线程,io线程负责登陆主节点监控和抓取主节点的binlog日志信息到当前节点的relay中继日志中,sql线程负责执行中继日志中抓取到的sql语句,从而实现mysql的主从复制。

主从复制的具体实现

登陆主节点查看主节点信息

代码语言:javascript
复制
mysql> show master status\G;
*************************** 1. row ***************************
             File: mysql-log.000005 二进制文件名称
         Position:   binlog日志指针位置
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
 row in set (0.00 sec)

登陆从节点挂载到主节点上

代码语言:javascript
复制
CHANGE MASTER TO
MASTER_HOST='10.9.104.184', --> 主节点ip地址
MASTER_PORT=, -->主节点mysql端口号
MASTER_USER='root',
MASTER_PASSWORD='root',
MASTER_LOG_FILE='mysql-log.000002',-->主节点二进制文件名称
MASTER_LOG_POS=主节点指针位置

最后不要忘了在从节点上执行如下sql,开启从节点角色

代码语言:javascript
复制
start slave

mysql的双机热备

其实就是让两个mysql互为主从,上述操作在两个mysql中换着操作一下就好

mysql的读写分离

在一个mysql集群中读写在不同的节点上操作,会大大的提升当前mysql集群的工作效率。但是这非常考验中间件的计算能力,下面介绍一下常用的中间件。

数据库常见的中间件

Cobar

阿里 b2b 团队开发和开源的,属于 proxy 层方案,就是介于应用服务器和数据库服务器之间。应用程序通过 JDBC 驱动访问 Cobar 集群,Cobar 根据 SQL 和分库规则对 SQL 做分解,然后分发到 MySQL 集群不同的数据库实例上执行。早些年还可以用,但是最近几年都没更新了,基本没啥人用,差不多算是被抛弃的状态吧。而且不支持读写分离、存储过程、跨库 join 和分页等操作。

TDDL

淘宝团队开发的,属于 client 层方案。支持基本的 crud 语法和读写分离,但不支持 join、多表查询等语法。目前使用的也不多,因为还依赖淘宝的 diamond 配置管理系统。

Atlas

360 开源的,属于 proxy 层方案,以前是有一些公司在用的,但是确实有一个很大的问题就是社区最新的维护都在 5 年前了。所以,现在用的公司基本也很少了。

Sharding-jdbc

当当开源的,属于 client 层方案,目前已经更名为 ShardingSphere(后文所提到的 Sharding-jdbc,等同于 ShardingSphere)。确实之前用的还比较多一些,因为 SQL 语法支持也比较多,没有太多限制,而且截至 2019.4,已经推出到了 4.0.0-RC1 版本,支持分库分表、读写分离、分布式 id 生成、柔性事务(最大努力送达型事务、TCC 事务)。而且确实之前使用的公司会比较多一些(这个在官网有登记使用的公司,可以看到从 2017 年一直到现在,是有不少公司在用的),目前社区也还一直在开发和维护,还算是比较活跃,个人认为算是一个现在也可以选择的方案。

mycat

Mycat 基于 Cobar 改造的,属于 proxy 层方案,支持的功能非常完善,而且目前应该是非常火的而且不断流行的数据库中间件,社区很活跃,也有一些公司开始在用了。但是确实相比于 Sharding jdbc 来说,年轻一些,经历的锤炼少一些。 主要介绍一下mycat是如何实现数据库的故障转移,和读写分离的

基于mycat的一些配置

进入mycat的conf目录下会有一些mycat的配置文件,下面我来一 一解读

server.xml
代码语言:javascript
复制
[root@10-42-99-103 conf]# vim server.xml

                <!--<property name="processorExecutor">16</property>-->
                <!-- 
                        <property name="mutiNodeLimitType">1</property> 0:开启小数量级(默认) ;1:开启亿级数
据排序
                <property name="mutiNodePatchSize">100</property> 亿级数量排序批量
                        <property name="processors">32</property> <property name="processorExecutor">32</property> 
                        <property name="serverPort">8066</property> <property name="managerPort">9066</property> 
                        <property name="idleTimeout">300000</property> <property name="bindIp">0.0.0.0</property> 
                        <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->
        </system>
        <user name="root">
                <property name="password">root</property>
                <property name="schemas">mycatdb</property>
        </user>

        <!--<user name="user">
                <property name="password">user</property>
                <property name="schemas">TESTDB</property>
                <property name="readOnly">true</property>
        </user>-->
        <!-- 
        <quarantine> 
           <whitehost>
              <host host="127.0.0.1" user="mycat"/>
              <host host="127.0.0.2" user="mycat"/>
           </whitehost>
       <blacklist check="false"></blacklist>
        </quarantine>
        -->

</mycat:server>
代码语言:javascript
复制
配置mycat作为服务器的一些资源配置,端口占用,线程数量
连接数量,登录用户,权限设置。
<system> 
包含了mycat作为一个软件需要配置的所以系统信息
<property name="defaultSqlParser">druidparser</property>
默认的sql语句拦截器阿里的德鲁伊拦截器,maycat作为一个数据库
的中间件,需要对前端连接的sql语句进行拦截。
<property name="useCompression">1</property><!--1为开启mysql压缩协议-->
<user>
定义了可以访问登陆mycat的用户信息和权限
<quarantine> 
mycat的防火墙可以进行安全级别的配置
<whitehost>
访问mycat的白名单(ip地址 和用户名)
<blacklist check="false"></blacklist>
sql语句的黑名单
可以定义什么sql语句可以被执行,什么样的sql语句不能被执行
schema.xml
代码语言:javascript
复制
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://org.opencloudb/" >

        <schema name="mycatdb" checkSQLschema="true" sqlMaxLimit="100">
                <!--mstest.user demo01-->
               <table name="t_order" primaryKey="order_id" dataNode="dn1,dn2"
                rule="easymall-order">
                        <childTable name="t_order_item"
                                primaryKey="ID" joinKey="order_id" parentKey="order_id"/>
                </table>
        </schema>
        <!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743" 
                                     /> -->
        <dataNode name="dn1" dataHost="localhost1" database="easydb" />
        <dataNode name="dn2" dataHost="localhost2" database="easydb" />

        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
                writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <!--hostM1 HOSTM1S1 HOSTM1S2 HOSTM1S3
                                                             HOSTM2 HOSTM2S1 HOSTM2S2-->
                <writeHost host="hostM2" url="10.42.167.114:3306" user="root"
                        password="root">
                </writeHost>
        </dataHost>

        <dataHost name="localhost2" maxCon="1000" minCon="10" balance="1"
                writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="hostM1" url="10.42.99.103:3306" user="root"
                        password="root">
                </writeHost>
        </dataHost>
代码语言:javascript
复制
<schema>
定义mycat中作为服务器给客户端使用的逻辑库,逻辑库中的数据
可以来源于一个真是库,也可以来源于多个真实库。
<schema name="mycatdb" checkSQLschema="true" sqlMaxLimit="100">
checkSQLschema:是否自动添加库名作为表的前缀
sqlMaxLimit="100"每次查询最多查100条数据
<table>  定义逻辑库中的逻辑表,逻辑表的名字必须与真实表的名字保持一致
<table name="company" primaryKey="ID" dataNode="dn3,dn2,dn1" rule="mod-long"/>
name:逻辑表的名字
primaryKey:逻辑表的主键默认为ID(不区分大小写)
dataNode:定义当前逻辑表的数据分片来源
代码语言:javascript
复制
使用mycat实现数据库读写分离,故障转移的高可用结构
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
	writeType="0" dbType="mysql" 
		dbDriver="native" switchType="1"  slaveThreshold="100">
switchType(默认为1)可以-1也可以1,为1时支持故障转移,当主节点
	发生故障宕机后会在writeHost中进行故障转移,实现数据库的高可用
writeType(默认为0)在当前dataHost的主从结构中,写操作只会在第一个writeHost中
进行。writeType=1:1.5版本后的mycat不推荐使用,因为在新版本中,读逻辑分离
开来由balance控制,如果writeType=1覆盖掉读逻辑,读写都随机在所有
的writeHost中完成,写操作会随机的在所有的writeHost中进行
读逻辑控制:(balance)
balance可以有0,1,2,3四个值当balance的值为0时(默认值也是0)不开启读的
分离,所有读操作都在第一个writeHost中进行。当balance的值为1时,开启读的分离
所有读操作大量分散在除第一个writeHost之外的所有writeHost和readHost中,当并发量
很大时,第一个writeHost也会分担一部分。当balance的值为2时读操作随机到所有的host
中执行。当balance的值为3时,所有的读操作都会分散到readHost中去,如果不存在readHost
则读操作会到第一个writeHost中去执行。
一般来讲,常见的读写分离配置为writeType=0,balance=1

使用mycat实现数据库的分布式结构(分片表格)
可以在schema.xml中的table标签中的dataNode属性中配置不同的数据分片
再根据rule属性配置相应的分片的匹配规则从而达到数据库的分布式的效果
rule.xml

为了实现mycat在不同数据分片中的数据一致性,mycat在rule.xml中定义了很多分片计算的规则。

全局表

因为mycat不支持跨分片查询,所以当有了多表联查的情景出现时 可能因为关联的表分散在两个不同的分片,可能出现数据丢失的 情况。当被关联的表的量不是很大,变化也不是很频繁的数据稳定 的情况下,可以把这张表放在所有的分片中,这张表就叫做全局表

全局表的特点

数据稳定,变化不大,量不大的工具字典表。

全局表的实现

在schema.xml的文件中定义逻辑表的时候不是用rule属性 改为 type="global"即可。

代码语言:javascript
复制
<table name="cat_test" primaryKey="ID" type="global"
dataNode="dn1,dn2"/>

ER分片表

思考全局表的概念,如果被关联的的表的量很大,数据变动很大 怎么办被关联的表还能用作全局表吗,如果可以,那么我们将表 进行水平拆分放在不同的库还有什么意义?所以就有了ER分片表的 概念,连接ER分片表之前要先理解什么是主表,什么是子表,子表 的数据是基于主表而存在,假设有两张表,一张表是北京市的父亲表 (父亲id,父亲姓名),另外一张表是北京市的儿子表(儿子id,儿子姓名) 为了使两张表产生关联,父亲id作为主键放到儿子表中。这时候儿子 表是基于父亲表存在的,如果父亲表没有了,就没有了关联的意义, 父亲表就是主表,儿子表就是子表,在使用分片计算逻辑时,对父亲 id进行运算就OK了,这就是ER分片表的设计思路。

ER分片表的实现

在schema.xml文件中使用如下配置定义逻辑表即可

代码语言:javascript
复制
<schema name="mycatdb" checkSQLschema="true" sqlMaxLimit="100">
           <!--mstest.user demo01-->
          <table name="father" primaryKey="father_id" dataNode="dn1,dn2"
           rule="father-child"> <!在rule.xml中将hash一致性算法的逻辑复置一份即可>
                   <childTable name="child"
                           primaryKey="ID" joinKey="father_id" parentKey="father_id"/>
           </table>
</schema>
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-06T,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 三范式和反三范式
  • mysql主从复制的原理
  • 主从复制的具体实现
  • mysql的双机热备
  • mysql的读写分离
  • 数据库常见的中间件
    • Cobar
      • TDDL
        • Atlas
          • Sharding-jdbc
            • mycat
            • 基于mycat的一些配置
              • server.xml
                • schema.xml
                  • rule.xml
                  • 全局表
                    • 全局表的特点
                    • 全局表的实现
                    • ER分片表
                      • ER分片表的实现
                      相关产品与服务
                      云数据库 MySQL
                      腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档