一、MariaDB在分布式系统里的核心定位
很多做后台开发的朋友应该都用过MySQL或者MariaDB,毕竟这俩都是关系型数据库里的“常青树”,但大部分人接触的都是单机版——一台服务器装个服务,存点业务数据,足够支撑小项目。可要是业务规模起来了,比如做电商、社交、在线教育这类用户量破百万、数据量破T的场景,单机版的问题就暴露了:要么读写速度慢到卡爆,要么单台服务器扛不住宕机风险,数据丢了直接损失惨重。
这时候就需要分布式系统来救场,简单说就是把数据拆成好几份,分别存在不同的服务器上,大家一起干活,分担压力还能互相备份。而MariaDB在分布式系统里的定位,就是“低成本、易维护的关系型数据存储核心”——它不像某些分布式数据库要重新学一套语法,基本和MySQL兼容,大部分开发者不用从零开始,就能快速把原来的单机业务迁移到分布式架构上。
二、MariaDB分布式架构的主流设计方案
现在市面上用MariaDB做分布式存储,最常用的有两种架构,一种是分库分表,另一种是基于Galera Cluster的集群架构,这两种方案各有各的适用场景,得根据业务需求选。
2.1 分库分表架构设计
分库分表的核心思路就是“拆”——把原来一个库里的表拆成多个库,或者把一个大表拆成多个小表,让每个库/表的数据量控制在合理范围内(一般建议单表数据量不超过千万,单库数据量不超过100G)。分库分表又分两种模式:垂直拆分和水平拆分。
垂直拆分就是按业务模块拆,比如原来一个库里有用户表、订单表、商品表,现在把用户相关的表放一个库,订单相关的放另一个库,商品的再放一个库,每个库单独部署在不同的服务器上。这种拆分适合业务模块清晰、各模块数据量都比较大的场景,比如电商平台的用户中心、订单中心、商品中心分开部署。
水平拆分就是按数据的某种规则拆,比如按用户ID的奇偶性拆,ID是奇数的放A库,偶数的放B库;或者按地域拆,华北的用户数据放北京的服务器,华南的放广州的服务器。这种拆分适合单表数据量特别大的场景,比如订单表,一年就能攒几千万甚至上亿条数据,垂直拆分解决不了问题,就得水平拆分。
这里给大家举个水平分表的完整示例,技术栈统一用Java + MyBatis Plus(一款常用的Java持久层框架,支持分库分表功能),假设我们要把用户订单表(order)按用户ID的末尾数字拆成10张表(order_0到order_9)。
首先得配置分表规则,MyBatis Plus的配置文件application.yml里要加上分表的配置:
# MyBatis Plus配置
mybatis-plus:
global-config:
db-config:
id-type: auto # 主键自增
# 分表规则配置
sharding:
tables:
# 订单表分表规则
order:
# 分表策略:按user_id的末尾数字取模
table-strategy:
standard:
sharding-column: user_id # 分表的字段
sharding-algorithm:
type: mod # 取模算法
params:
mod: 10 # 分10张表
然后写一个简单的订单插入的Java代码,带注释说明:
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.Date;
// 订单服务类,继承MyBatis Plus的ServiceImpl,简化CRUD操作
@Service
public class OrderService extends ServiceImpl<OrderMapper, Order> {
/**
* 插入订单,自动根据user_id路由到对应的分表
* @param userId 用户ID
* @param amount 订单金额
* @return 插入是否成功
*/
public boolean insertOrder(Long userId, BigDecimal amount) {
// 构造订单对象
Order order = new Order();
order.setUserId(userId); // 分表的核心字段,会被用来计算路由到哪张表
order.setAmount(amount);
order.setCreateTime(new Date()); // 订单创建时间
// 调用MyBatis Plus的插入方法,框架会自动根据分表规则路由
return save(order);
}
/**
* 根据用户ID查询订单,自动路由到对应的分表
* @param userId 用户ID
* @return 订单列表
*/
public List<Order> getOrdersByUserId(Long userId) {
// 构造查询条件,指定user_id,框架会自动路由到对应的分表
QueryWrapper<Order> wrapper = new QueryWrapper<>();
wrapper.eq("user_id", userId);
// 调用MyBatis Plus的查询方法
return list(wrapper);
}
}
这个示例里,不管是插入还是查询订单,开发者都不用手动写“根据user_id计算去order_几表”的逻辑,框架已经按配置的规则自动处理了,大大降低了开发难度。
2.2 Galera Cluster集群架构设计
如果说分库分表是“拆数据”,那Galera Cluster就是“复制数据”——它是MariaDB官方支持的一种多主同步复制集群,简单说就是集群里的所有节点都是主节点,都能读写,任何一个节点写的数据,都会同步到其他所有节点,数据完全一致。
这种架构的核心优势是高可用和强一致性:比如集群里有3个节点,就算其中1个节点宕机了,剩下的2个节点还能正常读写,不会影响业务;而且数据同步是同步的,不会出现主从复制那种延迟,适合对数据一致性要求特别高的场景,比如金融支付、订单库存扣减。
这里给大家举个Galera Cluster集群的配置示例,技术栈统一用MariaDB 10.6(目前稳定版),集群由3个节点组成,节点IP分别是192.168.1.10、192.168.1.11、192.168.1.12。
首先是每个节点的配置文件/etc/my.cnf,配置内容如下:
# 基础配置
[mysqld]
server-id = 1 # 每个节点的server-id必须唯一,10节点设为1,11设为2,12设为3
datadir = /var/lib/mysql # 数据目录
socket = /var/lib/mysql/mysql.sock
# Galera集群配置
wsrep_provider = /usr/lib/galera/libgalera_smm.so # Galera插件路径
wsrep_cluster_name = "mariadb_cluster" # 集群名称,所有节点必须一致
wsrep_cluster_address = "gcomm://192.168.1.10,192.168.1.11,192.168.1.12" # 所有节点的IP列表
wsrep_node_address = "192.168.1.10" # 当前节点的IP,11节点设为192.168.1.11,12设为192.168.1.12
wsrep_sst_method = rsync # 节点同步数据的方式,rsync适合小集群,大集群可以用xtrabackup
# 其他优化配置
binlog_format = ROW # 二进制日志格式,Galera要求必须是ROW
default_storage_engine = InnoDB # 默认存储引擎,Galera要求必须是InnoDB
innodb_autoinc_lock_mode = 2 # 自增锁模式,Galera要求必须是2
配置完之后,启动集群的第一个节点(192.168.1.10),命令如下:
# 启动第一个节点,需要加上--wsrep-new-cluster参数,初始化集群
systemctl start mariadb --wsrep-new-cluster
然后启动另外两个节点,直接启动服务即可,它们会自动加入集群:
# 启动11节点
systemctl start mariadb
# 启动12节点
systemctl start mariadb
集群启动完成后,可以在任意节点上执行命令,查看集群的状态,比如集群里的节点数量、数据同步状态:
# 登录MariaDB
mysql -u root -p
# 查看集群状态
show status like 'wsrep_cluster_size'; # 输出应该是3,代表集群有3个节点
show status like 'wsrep_incoming_addresses'; # 输出所有节点的IP列表
show status like 'wsrep_local_state_comment'; # 输出Synced代表当前节点数据同步正常
这个示例里,3个节点组成的集群,任何一个节点读写数据,都会自动同步到其他节点,就算某个节点宕机,其他节点还能继续工作,数据不会丢。
三、MariaDB分布式架构的应用场景
不同的架构对应不同的业务场景,选对架构才能事半功倍,下面给大家梳理几种常见的应用场景:
第一种是大流量读写场景,比如电商平台的秒杀活动,瞬间会有几十万甚至上百万的用户同时下单、查询商品,这时候用分库分表架构,把订单、商品数据拆分到多个服务器上,每个服务器只处理一部分请求,就能扛住大流量;如果用Galera Cluster,多节点读写也能分担压力,不过Galera的同步复制在大流量下可能会有性能损耗,所以分库分表更适合这种场景。
第二种是高可用场景,比如金融支付系统,一旦数据库宕机,用户就付不了款,损失会非常大,这时候用Galera Cluster集群,多节点互相备份,就算一个节点宕机,其他节点还能正常工作,而且数据强一致,不会出现支付成功但数据没同步的情况。
第三种是大数据量存储场景,比如社交平台的用户动态表,一年就能攒上亿条数据,单机版根本存不下,这时候用水平分表,把数据拆分到多个表甚至多个库,就能轻松存储海量数据。
第四种是多地域部署场景,比如做海外业务的公司,用户分布在全球各地,这时候可以用水平分表按地域拆分数据,把欧洲用户的数据存在欧洲的服务器,美洲的存在美洲的服务器,用户访问本地的服务器,速度会更快。
四、MariaDB分布式架构的优缺点分析
任何架构都不是完美的,MariaDB的分布式架构也有自己的优缺点,得根据业务需求权衡。
4.1 优点
首先是成本低,MariaDB是开源免费的,不用像某些商业分布式数据库那样付高额的授权费,而且它和MySQL兼容,大部分开发者不用重新学习,就能快速上手,降低了人力成本。
其次是易维护,分库分表的架构,每个库/表都是独立的,出问题了可以单独排查,不用动其他数据;Galera Cluster的集群,节点可以动态添加或删除,维护起来也很方便。
然后是兼容性好,MariaDB基本兼容MySQL的所有语法和工具,原来用MySQL的业务,迁移到MariaDB的分布式架构上,几乎不用改代码,大大降低了迁移成本。
最后是灵活性高,分库分表可以根据业务需求选择垂直拆分或水平拆分,Galera Cluster可以根据业务需求选择节点数量,适合不同规模的业务。
4.2 缺点
分库分表的架构,最大的缺点是跨库跨表查询麻烦,比如要查询用户的订单和商品信息,原来单机版一条SQL就能搞定,现在要分别去订单库和商品库查,然后在代码里拼接结果,增加了开发难度;而且分库分表要考虑主键自增的问题,比如多个库的主键不能重复,得用分布式主键(比如雪花算法)。
Galera Cluster的架构,最大的缺点是性能损耗,因为要同步数据到所有节点,写操作的性能会比单机版低,而且集群的节点数量越多,性能损耗越大,一般建议Galera集群的节点数量控制在3-5个;另外,Galera集群不支持跨集群复制,也不支持读写分离(所有节点都是主节点),如果要做读写分离,得额外加从节点。
五、MariaDB分布式架构的注意事项
用MariaDB做分布式架构,有几个注意事项必须要重视,不然很容易出问题。
第一是分表分库的规则要选对,比如按用户ID取模拆分,就要保证用户ID是均匀分布的,不然会出现某个分库/分表的数据量特别大,其他的特别小,导致负载不均;而且分表分库的规则一旦确定,就不能轻易改,不然要迁移数据,成本非常高。
第二是数据一致性要保证,分库分表的架构,跨库操作很容易出现数据不一致的情况,比如扣减库存和创建订单,要保证要么都成功,要么都失败,这时候就要用分布式事务(比如Seata)来保证;Galera Cluster虽然是强一致的,但也要注意节点的网络延迟,要是某个节点的网络延迟太高,会影响整个集群的性能。
第三是监控和备份要做好,分布式架构的节点多,出问题的概率也高,所以要做好监控,比如监控每个节点的CPU、内存、磁盘、网络,监控分库分表的路由是否正常,监控Galera集群的同步状态;备份也要做好,分库分表要每个库单独备份,Galera集群要定期全量备份,防止数据丢失。
第四是主键要统一,分库分表的架构,多个库的主键不能重复,所以不能用自增主键,要用分布式主键(比如雪花算法、UUID);Galera集群虽然支持自增主键,但要配置正确的自增锁模式,不然会出现主键冲突。
第五是避免大事务,不管是分库分表还是Galera Cluster,大事务都会影响性能,比如一次插入几万条数据,会导致锁表时间太长,其他请求都要等待,所以要尽量拆分大事务,比如一次插入1000条数据,分多次插入。
六、文章总结
MariaDB作为一款开源免费、兼容MySQL的关系型数据库,在分布式系统中有着广泛的应用,它的分库分表架构适合大流量、大数据量的场景,Galera Cluster架构适合高可用、强一致的场景,开发者可以根据自己的业务需求选择合适的架构。
不过MariaDB的分布式架构也有自己的优缺点,比如分库分表的跨库查询麻烦,Galera Cluster的性能损耗大,所以在使用的时候要注意选对架构、做好分库分表规则、保证数据一致性、做好监控和备份、避免大事务等问题。
总的来说,MariaDB的分布式架构是一种低成本、易维护的关系型数据存储方案,适合大部分中小规模的业务,甚至一些大规模的业务也能通过优化架构来支撑,是开发者做分布式系统时的一个不错的选择。
Comments