读写分离,分库分表
数据切分
将存储在一台数据库上的数据,分散到多台数据库中,以此达到降低单台数据库负载的效果
垂直切分
- 按照不同的表或者schema切分到不同的数据库中
- 规则简单,易于实施,可以根据业务模块进行划分,各个业务之间耦合性低,相互影响较小
- 优点
- 拆分后业务清晰,拆分规则明确
- 系统之间容易扩展和整合
- 数据维护简单
- 缺点
- 部分业务表无法join,只能通过接口调用,提升了系统的复杂度
- 跨库事务难以处理
- 垂直切分后,某些业务数据庞大,仍然存在单体性能瓶颈
水平切分
- 将一张表中的数据,根据某种规则拆分到不同的数据库中
- 优点
- 解决了单库大数据,高并发的性能瓶颈
- 拆分规则封装好,对应用端几乎透明,开发人员无需关心拆分细节
- 提高了系统的稳定性和负载能力
- 缺点
- 拆分规则很难抽象
- 分片事务一致性难以解决
- 二次扩展时,数据迁移,维护难度大
数据库读写分离
- 弊端(当同步挂掉,或者延迟比较大,写库和读库的数据不一致)
- 对数据实时性要求不高的业务场景
安装
wget https://dev..com/get/mysql80-community-release-el7-3.noarch.rpm
rpm -ivh 80-community-release-el7-3.noarch.rpm
yum install -community-server
systemctl start d
# 查看临时密码
grep password /var/log/d.log
# 登录修改密码
alter user 'root'@'localhost' identified by 'Learn@123456';
flush privileges;
# 新建用户
create user 'learn'@'%' identified with _native_password by 'Learn@123456';
# 授权
grant all on *.* to 'learn'@'%';
flush privileges;
主从配置
- 主配置log-bin,指定文件的名字
- 主配置server-id,默认为1
- 从配置server-id,与主不能重复
- 配置示例
# 主
vim /etc/my.cnf
log-bin=learn_
server-id=1
# 从
server-id=2
- 主创建备份账户并授权REPLICATION SLAVE
create user 'repl'@'%' identified by 'Learn@123456';
grant replication slave on *.* to 'repl'@'%';
flush privileges;
- 主进行锁表FLUSH TABLES WITH READ LOCK;
- 主找到log-bin的位置SHOW MASTER STATUS;
- 主备份数据
mysqldump --all-databases --master-data>dbdump.db
- 主解锁表
unlock tables;
- 从
mysql < dbdump.db -uroot -p
- 在从上设置主的配置
change master to
-> master_host='192.168.150.90',
-> master_user='repl',
-> master_password='Learn@123456',
-> master_log_file='learn_mysql.000001',
-> master_log_pos=857;
- 从执行START SLAVE
mycat
- 开源的分布式数据库系统,前端的用户可以将其看成一个数据库代理,用客户端和命令行工具都可以访问,而后端则是用mysql原生的协议与多个mysql服务之间通信
- 数据库中间件,不仅仅可以用作读写分离,分库分表,还可以用于容灾备份,云平台建设等
应用场景
- 单纯的读写分离,此时配置简单,支持读写分离,主从切换
- 分库分表,对于超过1000w的表进行分片,最大支持1000亿的数据
- 多租户应用,每个应用一个数据库,应用只连接mycat,程序本身不需要改造
- 代替Hbase,分析大数据
基本概念
- 逻辑库(一个或多个数据库集群构成逻辑库)
- 逻辑表(读写数据的表就是逻辑表)
- 分片节点(数据被切分后,一张大表被分到不同的分片数据库上,每个所在的数据库就叫做分片节点)
- 节点主机(数据切分后,每一个分片节点不一定都会占用一个真正的物理主机,会存在多个分片节点在同一台物理主机上的情况,这些分片节点所在的主机叫做节点主机)
- 分片规则(一张大表被拆分成多个分片表,就需要一定的规则,按照某种业务逻辑,将数据分到一个确定的分片中,这个规则即分片规则)
- 全局序列号(唯一标识)
配置
- 用户配置
# server.xml
# 配置mycat的用户名,密码,权限,schema等
# 如同给新建用户
# 客户端连接mycat与连接无异
<mycat:server>
......
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
</user>
<user name="user">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
</user>
</mycat:server>
- schema.xml配置
# 配置dataHost(节点主机),包括读host,写host
# 配置dataNode(数据节点),自定到具体的数据库
# 配置schema,表名,数据节点,分片规则
# balance:负载均衡类型:0不开启读写分离;1(双主双从:读在后3台,写在第一台)和
# 2(所有读操作随机分配)均读写分离;3读落在readHost上
# schema标签中,checkSQLschema默认保留就好
# sqlMaxLimit:select默认的limit值,仅对分片有效
# rule属性:定义分片表的分片规则,必须与rule.xml中的tableRule对应
# ruleRequired属性,是否绑定分片规则,如果为true,没有绑定分片规则,程序报错
分片规则
- 枚举分片
# 适合特定的场景,通过在配置文件中配置可能的枚举id,自己配置分片
# schema.xml
<table name="user" dataNode="dn90,dn91" rule="sharding-by-intfile" />
# rule.xml
<tableRule name="sharding-by-intfile">
<rule>
<columns>province_id</columns>
<algorithm>hash-int</algorithm>
</rule>
</tableRule>
<function name="hash-int"
class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
# 设置默认节点
<property name="defaultNode">0</property>
</function>
# partition-hash-int.txt
DEFAULT_NODE=0
- 取模
# schema.xml
<table name="user" dataNode="dn90,dn91" rule="mod-long" />
# rule.xml
<tableRule name="mod-long">
<rule>
<columns>user_id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name="mod-long"
class="io.mycat.route.function.PartitionByMod">
# 设置节点数量
<property name="count">2</property>
</function>
全局表
- 不需要分片的表
- type属性:global为全局表,不指定则为分片表
<table name="province" dataNode="dn90,dn91" type="global" />
子表
- childTable,定义分片子表
- name属性,子表名称
- joinKey属性,标志子表中的列,用于与父表做关联
- parentKey标签,标志父表中的列,与joinKey对应
- primaryKey属性,子表主键,同table标签
- needAddLimit属性,同table标签
- 配置示例
# schema.xml
<table name="o_order" dataNode="dn90,dn91" rule="auto-sharding-long">
<childTable name="order_item" joinKey="order_id" parentKey="id"/>
</table>
高可用
- 安装proxy
yum -y install haproxy.x86_64
vi /etc/haproxy/haproxy.cfg
# 部分配置
defaults
mode tcp
backend app
balance roundrobin
server app1 192.168.150.90:8066 check
server app1 192.168.150.92:8066 check
# 启动
haproxy -f /etc/haproxy/haproxy.cfg
- 安装keepalived
yum install -y keepalived.x86_64
vi /etc/keepalived/keepalived.conf
# 部分配置
参考keepalived配置
sharding-jdbc
- 开源分布式的关系型数据库中间件
- 客户端代理模式
- 定位为轻量级的Java框架,以jar包提供服务
- 可以理解为增强版的jdbc驱动
- 兼容各种ORM框架
- 与mycat的区别
- mycat是服务端代理sharding-jdbc是客户端代理
- mycat不支持同一库内的水平切分,sharding-jdbc支持
- 部分配置
## 数据源
spring.shardingsphere.datasource.names=ds0,ms1,slave0
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.jdbcUrl=jdbc:mysql://192.168.150.90:3306/sharding_order
spring.shardingsphere.datasource.ds0.username=learn
spring.shardingsphere.datasource.ds0.password=Learn@123456
spring.shardingsphere.datasource.ms1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ms1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ms1.jdbcUrl=jdbc:mysql://192.168.150.91:3306/shard_order
spring.shardingsphere.datasource.ms1.username=learn
spring.shardingsphere.datasource.ms1.password=Learn@123456
spring.shardingsphere.datasource.slave0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.slave0.jdbcUrl=jdbc:mysql://192.168.150.92:3306/shard_order
spring.shardingsphere.datasource.slave0.username=learn
spring.shardingsphere.datasource.slave0.password=Learn@123456
## 表
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ms$->{0..1}.t_order${1..2}
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression=ms${user_id%2}
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_${id%2+1}
## 全局表
spring.shardingsphere.sharding.broadcast-tables=area
## 读写分离
spring.shardingsphere.sharding.master-slave-rules.ms0.master-data-source-name=ds0
spring.shardingsphere.sharding.master-slave-rules.ms0.slave-data-source-names.=slave0
spring.shardingsphere.sharding.master-slave-rules.ms0.load-balance-algorithm-type=RANDOM
## mybatis
mybatis.mapper-locations=/mybatis/*.xml