当前位置: 首页 > news >正文

【架构实战】读写分离中间件对比(ShardingSphere/MyCat)

一、为什么需要读写分离

在大多数互联网应用中,读操作远多于写操作:

读请求:70-80% 写请求:20-30%

单机数据库的问题:

主库:处理所有写请求 + 部分读请求 ↓ 连接池耗尽 → 响应变慢 → 用户投诉

解决方案:读写分离

写请求 ──► 主库 │ 读请求 ──┼──► 从库1 │ └──► 从库2

二、ShardingSphere实战

1. ShardingSphere-JDBC

架构:

应用 ──► ShardingSphere-JDBC(嵌入应用) ├── 改写SQL ├── 路由到正确的数据源 └── 结果合并 │ ┌────┼────┐ ▼ ▼ ▼ 主库 从库1 从库2

依赖配置:

<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core</artifactId><version>5.3.0</version></dependency>

数据源配置:

# application.ymlspring:shardingsphere:datasource:names:master,slave0,slave1master:type:com.zaxxer.hikari.HikariDataSourcedriver-class-name:com.mysql.cj.jdbc.Driverjdbc-url:jdbc:mysql://192.168.1.100:3306/order_dbusername:rootpassword:passwordslave0:type:com.zaxxer.hikari.HikariDataSourcedriver-class-name:com.mysql.cj.jdbc.Driverjdbc-url:jdbc:mysql://192.168.1.101:3306/order_dbusername:rootpassword:passwordslave1:type:com.zaxxer.hikari.HikariDataSourcedriver-class-name:com.mysql.cj.jdbc.Driverjdbc-url:jdbc:mysql://192.168.1.102:3306/order_dbusername:rootpassword:passwordrules:readwrite_splitting:data-sources:ds_master_slave:type:Staticprops:write-data-source-name:masterread-data-source-names:slave0,slave1load-balancer:type:ROUND_ROBINprops:alpha:5# 强制路由到主库(写操作后立即读取)props:query-with-connection-preference:true

Java配置方式:

@ConfigurationpublicclassShardingSphereConfig{@BeanpublicDataSourcedataSource(){Map<String,DataSource>dataSourceMap=newHashMap<>();// 主库DataSourcemaster=createDataSource("jdbc:mysql://192.168.1.100:3306/order_db");dataSourceMap.put("master",master);// 从库1DataSourceslave0=createDataSource("jdbc:mysql://192.168.1.101:3306/order_db");dataSourceMap.put("slave0",slave0);// 从库2DataSourceslave1=createDataSource("jdbc:mysql://192.168.1.102:3306/order_db");dataSourceMap.put("slave1",slave1);// 读写分离配置ReadwriteSplittingDataSourceRuleConfigurationdataSourceConfig=newReadwriteSplittingDataSourceRuleConfiguration("ds_master_slave",// 数据源名称"master",// 主库Arrays.asList("slave0","slave1"),// 从库"round_robin"// 负载均衡策略);// 负载均衡配置Propertiesprops=newProperties();props.setProperty("alpha","5");// 权重Map<String,DataSource>dataSources=newHashMap<>();dataSources.put("ds_master_slave",ReadwriteSplittingDataSourceFactory.create(dataSourceMap,dataSourceConfig,props));returndataSources.get("ds_master_slave");}}

强制路由到主库:

// 使用Hint强制路由到主库HintManagerhintManager=HintManager.getInstance();hintManager.setMasterRouteOnly();// 写完数据后立即读取,走主库try(HintManagerhintManager=HintManager.getInstance()){hintManager.setMasterRouteOnly();Orderorder=orderService.createOrder(request);// 这里读取走主库returnorderService.getOrder(order.getId());}

2. ShardingSphere-Proxy

架构:

应用(不需要修改)──► MySQL Client │ ShardingSphere-Proxy (独立的MySQL服务进程) │ ┌──────────┼──────────┐ ▼ ▼ ▼ 主库 从库1 从库2

Docker部署:

# docker-compose.ymlversion:'3'services:shardingsphere-proxy:image:apache/shardingsphere-proxy:5.3.0container_name:shardingsphere-proxyports:-"3307:3307"environment:MODE_TYPE:StandaloneJVM_OPTS:"-Xmx512m -Xms512m"volumes:-./conf:/opt/shardingsphere-proxy/confnetworks:-shardingspherenetworks:shardingsphere:driver:bridge

server.yaml配置:

# conf/server.yamlschemaName:readwrite_splittingdataSources:ds_master:url:jdbc:mysql://192.168.1.100:3306/order_db?serverTimezone=UTCusername:rootpassword:passwordconnectionPoolClassName:com.zaxxer.hikari.HikariDataSourcemaxPoolSize:50minPoolSize:10ds_slave_0:url:jdbc:mysql://192.168.1.101:3306/order_db?serverTimezone=UTCusername:rootpassword:passwordconnectionPoolClassName:com.zaxxer.hikari.HikariDataSourcemaxPoolSize:50minPoolSize:10ds_slave_1:url:jdbc:mysql://192.168.1.102:3306/order_db?serverTimezone=UTCusername:rootpassword:passwordconnectionPoolClassName:com.zaxxer.hikari.HikariDataSourcemaxPoolSize:50minPoolSize:10rules:-!readwrite_splittingdataSources:prds:type:Staticprops:write-data-source-name:ds_masterread-data-source-names:ds_slave_0,ds_slave_1loadBalancerName:round_robinloadBalancers:round_robin:type:ROUND_ROBIN

应用连接:

// 应用连接ShardingSphere-Proxy(像连接普通MySQL一样)Stringurl="jdbc:mysql://192.168.1.100:3307/readwrite_splitting";

三、MyCat实战

1. MyCat安装

# 下载wgethttp://dl.mycat.org.cn/2.0/Mycat-server-2.0.0-release/tar-zxfMycat-server-2.0.0-release.tar.gz-C/usr/local/# 配置环境变量exportMYCAT_HOME=/usr/local/mycatexportPATH=$PATH:$MYCAT_HOME/bin# 启动mycat start# 查看状态mycat status

2. server.xml配置

<!-- conf/server.xml --><?xml version="1.0" encoding="UTF-8"?><!DOCTYPEmycat:serverSYSTEM"server.dtd"><mycat:serverxmlns:mycat="http://io.mycat/"><system><propertyname="defaultSqlParser">druidparser</property><propertyname="serverPort">8066</property><propertyname="managerPort">9066</property></system><username="root"><propertyname="password">password</property><propertyname="schemas">order_db</property></user></mycat:server>

3. schema.xml配置

<!-- conf/schema.xml --><?xml version="1.0" encoding="UTF-8"?><!DOCTYPEmycat:schemaSYSTEM"schema.dtd"><mycat:schemaxmlns:mycat="http://io.mycat/"><schemaname="order_db"checkSQLschema="false"sqlMaxLimit="100"><!-- 定义逻辑表(可选) --><tablename="order"primaryKey="id"dataNode="dn1,dn2"/></schema><!-- 数据节点 --><dataNodename="dn1"dataHost="dh1"database="order_db"/><dataNodename="dn2"dataHost="dh2"database="order_db"/><!-- 数据主机(读写分离) --><dataHostname="dh1"maxCon="1000"minCon="10"balance="1"writeType="0"dbType="mysql"dbDriver="native"><heartbeat>select user()</heartbeat><!-- 写库 --><writeHosthost="hostM1"url="192.168.1.100:3306"user="root"password="password"><!-- 读库 --><readHosthost="hostS1"url="192.168.1.101:3306"user="root"password="password"/><readHosthost="hostS2"url="192.168.1.102:3306"user="root"password="password"/></writeHost></dataHost></mycat:schema>

4. balance负载均衡策略

策略说明适用场景
0所有读操作发送到writeHost不推荐,可能读到旧数据
1读操作分发到所有readHost常用,读写分离
2随机分发到readHost不推荐
3只分发到readHost,无可用则writeHost读写分离+高可用

推荐配置:

<dataHostname="dh1"balance="1"writeType="0"><!-- balance=1:读操作分发到所有readHost --></dataHost>

四、ShardingSphere vs MyCat对比

维度ShardingSphereMyCat
架构JDBC层(轻量)独立服务(重量)
部署嵌入应用/独立Proxy独立部署
性能较高略低
维护社区活跃社区相对沉寂
分库分表支持支持
读写分离支持支持
学习成本较高
配置复杂度

五、读写分离最佳实践

1. 什么时候用读写分离

适合场景:

  • 读多写少(读:写 >= 7:3)
  • 单机数据库成为瓶颈
  • 数据量适中(单表<1000万)

不适合场景:

  • 写多读少
  • 强一致性要求(读写分离有延迟)
  • 单表数据量过亿(需要分库分表)

2. 读写延迟处理

方案1:强制路由到主库

// ShardingSpheretry(HintManagerhintManager=HintManager.getInstance()){hintManager.setMasterRouteOnly();returnorderMapper.selectById(id);}

方案2:应用层判断

publicOrdergetOrderAfterCreate(LongorderId){// 创建订单后,等待一小段时间让主从同步完成// 然后可以走从库Orderorder=orderMapper.selectById(orderId);// 如果是刚创建的,从主库读if(order.getCreateTime().isAfter(LocalDateTime.now().minusSeconds(5))){returngetOrderFromMaster(orderId);}returnorder;}

3. 监控配置

spring:shardingsphere:rules:readwrite-splitting:data-sources:ds_0:type:Staticload-balancer:type:ROUND_ROBINprops:# 开启SQL日志sql-show:true
-- MyCat监控mysql-h192.168.1.100-P9066-u root-ppassword-e"show @@datanode;"mysql-h192.168.1.100-P9066-u root-ppassword-e"show @@heartbeat;"

六、总结

读写分离是提升数据库读性能的有效手段:

  • ShardingSphere:轻量级,嵌入应用,易于使用
  • MyCat:独立服务,功能强大但配置复杂
  • 强制主库路由:解决读写延迟问题
  • 监控告警:确保复制健康

选型建议:

  1. 新项目推荐ShardingSphere
  2. 需要分库分表优先ShardingSphere
  3. 遗留系统改造可选MyCat

思考题:你们用的什么读写分离方案?有没有遇到过主从延迟的问题?


个人观点,仅供参考

http://www.jsqmd.com/news/585748/

相关文章:

  • 效率提升秘籍:用快马AI一键生成openclawskills网站核心功能模块代码
  • Qwen-Image-Layered体验报告:实测一键图片分层,效果惊艳,操作简单
  • 仲景中医大语言模型:革新性传统医学与AI融合的突破性解决方案
  • 回溯算法终极指南:LeetCode排列组合问题的10个实战技巧
  • 百度网盘下载限速终结者:3分钟解锁全速下载的智能解析方案
  • 【无人机三维路径规划】基于matlab蚁群算法ACA、Astar和遗传GA算法无人机山地路径规划【含Matlab源码 15285期】
  • 新型TyG复合指标——TyHGB上线CHARLS公共数据库平台啦!
  • 2026年本地齿轮链轮实力厂家推荐,适配复杂工况的有哪些? - 工业设备
  • Blender3mfFormat:专业3MF文件处理插件完全指南
  • 终极优化指南:WeChatExtension-ForMac从卡顿到流畅的蜕变之旅
  • 霜儿-汉服-造相Z-Turbo应用:为文化活动批量生成宣传素材
  • Mac Mouse Fix:5分钟让你的普通鼠标变身macOS生产力神器
  • 抖音无水印下载实战指南:5步破解技术壁垒的完整方案
  • Lepton AI零售分析:客户行为预测服务实践指南
  • 本地齿轮链轮大型厂家哪家好用,价格费用大概多少钱? - 工业品网
  • CasRel模型.NET平台集成案例:开发企业内网知识管理插件
  • ClusterFuzz终极内存泄漏检测指南:LSAN与UBSAN的完整配置教程
  • 如何利用QOwnNotes托盘图标提升效率:快速访问与系统通知设置终极指南
  • 为什么你的电脑风扇总是太吵或太热?Fan Control的智能解决方案
  • ModTheSpire深度解析:如何为《杀戮尖塔》构建无侵入式模组生态
  • 总结2026年口碑不错的欧洲进口地板机构,哪家服务更贴心? - 工业推荐榜
  • 企业级本地化离线OCR解决方案:Umi-OCR的技术实践与价值挖掘
  • LLMLingua三版本终极指南:如何选择最适合的提示压缩方案
  • League-Toolkit:提升80%游戏效率的英雄联盟全能辅助解决方案
  • 3大核心功能让你轻松搞定美团神券:告别手动抢券的智能助手使用指南
  • 动态规划终极指南:从LeetCode算法题掌握高效解题思维
  • 分析2026年武汉本地齿轮制作厂家,怎么选择更靠谱 - myqiye
  • 终极指南:3分钟让Android Studio界面变中文,告别英文困扰
  • 新手福音:在快马平台用AI引导轻松入门PostgreSQL数据库操作
  • 虚拟手柄革命:用vJoy解锁游戏控制的无限可能