分享

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

 知行合一ing 2018-12-10

一、为什么要分库分表

解决大数据存储时数据访问性能,具体来说就是解决超大容量问题和性能问题。

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

二、如何分库分表

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

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

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

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

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

三、常见拆分策略

垂直拆分:按照功能模块、业务维度、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=3306default-character-set=utf8[mysqld]#主库配置server-id=1log-bin=mysql-binlog-bin-index=mysql-bin.index#端口port=3306character_set_server=utf8#设置数据库引擎为INNODBdefault-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=3307default-character-set=utf8[mysqld]#主库配置server-id=2relay-log=slave-relay-binrelay-log-index=slave-relay-bin.indexread_only=1#端口port=3307character_set_server=utf8#设置数据库引擎为INNODBdefault-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;

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多