数据库分库分表及MySQL主从复制实现数据库同步

一、为什么要分库分表
解决大数据存储时数据访问性能,具体来说就是解决超大容量问题和性能问题。

举例说明,订单表或用户表如果数据量达到上亿条记录,此时数据库的IO能力、处理能力就会出现一个瓶颈(MySQL官方统计单表数据量超过1000万性能会逐渐下降)。另一方面,单一数据库本身的CPU、内存、磁盘、IO都有性能极限。

二、如何分库分表
垂直分库:解决数据表过多问题,按照功能模块、业务维度、ER图、领域模型等把相关联的表部署在一个数据库上。

垂直分表:解决单表列数过多或大字段性能问题问题,按照列划分为几个小的数据表。如果一张表中有一个大字段,而且并不是必须要展示的或者不是当前需要用的,那么虽然没有刻意去查询,但是在根据id或者其他索引进行查询的时候就会把大字段一起查出来,会严重影响查询的性能,所以才有的垂直分表。
 

 

水平分表:解决数据量过大问题,把数据存储到结构相同的不同表中。比如3000万订单数据,分别存放到三张表中,每张表存放1000万数据。

三、常见拆分策略
垂直拆分:按照功能模块、业务维度、ER图、领域模型等进行表划分,将相关联的表放到统一数据库中,避免跨库关联join

水平拆分:

1)一致性Hash:例如订单表,可以按照订单userid字段进行哈希取模算法,路由映射到不同表或数据库中。一致性Hash数据存储具有随机性。

2)范围切分:按照某个字段(例如ID)在某个维度区间将数据路由映射到不同表或数据库中。例如ID=0~100000之间的数据保存奥数据库DB1,ID=100001~200000之间的数据保存至数据库DB2。范围切分能保证数据是连续的。

3)日期拆分:例如当前一年的业务数据存放到生产库,将一年前的数据备份至备份库中。

四、拆分以后带来的问题
1)跨库join的问题,select a.x,b.y from user a join merchant b on a.id=b.userid

解决方法:

设计的时候充分考虑到应用层的join问题,尽量避免跨库join;

关联表数据可以通过服务层去远程RPC调用,例如上述sql语句,可以先本地查询出a表数据,然后通过远程RPC调用获取关联b表数据;

创建全局表,即在每个数据库中都创建相同的表,数据变更较少的基于全局应用的表;

做字段冗余,用空间换时间,例如在订单表中保存商户id,商户名称。

2)跨分片数据排序分页

解决方法:

在应用层进行数据拼接,对每个表中的数据进行查询,然后按照排序字段再进行数据拼接。

3)唯一主键问题,例如用自增ID做主键,分库后必然会出现重复主键

解决方法:

用UUID作为主键,UUID字符串比较大,造成生成的索引较大,性能较低;

利用Snowflake雪花算法生成主键,根据时间序列、机器标识、技术顺序号,按照指定算法生成唯一ID;

借助MongoDB的ObjectId作为唯一主键;

借助zookeeper自动生成递增ID作为唯一主键。

4)分布式事务

多个数据库表之间保证原子性

五、MySQL主从复制实现数据库同步
绝大部分应用是一个写少读多的操作,只读数据库会从主数据库同步数据。MySQL数据库的读写分离,通常做法是采用MySQL主从复制实现数据库同步,由从数据库提供只读操作。这里以windows环境下简要说明MySQL主从配置,实现主从数据库的数据同步。MySQL数据库版本mysql-5.6.32-winx64,主数据库端口号3306,从数据库端口号3307。

1)主库(master)的配置

进入主库mysql-5.6.32-winx64目录中,在此目录中新建my.ini文件并添加一下配置。

[client]
port=3306
default-character-set=utf8
[mysqld]
#主库配置
server-id=1
log-bin=mysql-bin
log-bin-index=mysql-bin.index
#端口
port=3306
character_set_server=utf8
#设置数据库引擎为INNODB
default-storage-engine=INNODB
#设置mysql服务器字符集
collation-server=utf8_general_ci
#解压目录
basedir=D:\mysql-5.6.32-winx64
#解压目录下data目录
datadir=D:\mysql-5.6.32-winx64\data

2)从库(slave)的配置

进入主库mysql-5.6.32-winx64目录中,在此目录中新建my.ini文件并添加一下配置。

[client]
port=3307
default-character-set=utf8
[mysqld]
#主库配置
server-id=2
relay-log=slave-relay-bin
relay-log-index=slave-relay-bin.index
read_only=1
#端口
port=3307
character_set_server=utf8
#设置数据库引擎为INNODB
default-storage-engine=INNODB
#设置mysql服务器字符集
collation-server=utf8_general_ci
#解压目录
basedir=D:\mysql-5.6.32-winx64
#解压目录下data目录
datadir=D:\mysql-5.6.32-winx64\data

3)关联主库(master)与从库(slave)

主从数据库启动成功后,分别执行show master status;和show slave status\G;查看主从数据库状态。此时主库(master)下生成了一个二进制的日志文件,而slave下是空的,所以就要把主库与从库关联起来,即只需要让从库(slave)知道主库(master)的地址就可以了。在从库(slave)执行如下命令,将主库与从库联系起来,然后执行命令start slave开启主从同步。

master_host='localhost',master_port=3306,master_user='root',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=120;

3)主从同步原理

 

1、master记录二进制日志。在每个事务更新数据完成之前,master会在二进制日志中记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。

2、slave将master的binary log拷贝到它自己的中继日志。slave首先会开始一个工作线程即I/O线程,I/O线程在master上打开一个普通的连接,之后开始binlog dump process。binlog dump process从master的二进制日志中读取事件并写入中继日志,如果已经跟上master,它会睡眠并等待master产生新的事件。

3、SQL线程从中继日志读取事件,并重放其中的事件去更新slave的数据,使其与master中的数据一致。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值