news 2026/10/17 13:51:47

2.5 读写分离进阶:从单点到30个读节点的架构演进

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
2.5 读写分离进阶:从单点到30个读节点的架构演进

2.5 读写分离进阶:从单点到30个读节点的架构演进

📚 学习目标

通过本节学习,你将掌握:

  • ✅ 读写分离架构的演进路径和设计原则
  • ✅ 从单点到多读节点的架构设计方法
  • ✅ 负载均衡、故障转移等关键技术
  • ✅ 数据一致性保障和延迟处理
  • ✅ 大规模读节点的运维和监控

🎯 学习收获

学完本节后,你将能够:

  1. 架构演进:设计从单点到多读节点的演进路径
  2. 负载均衡:实现高效的读请求负载均衡
  3. 故障处理:处理读节点故障和主从延迟问题
  4. 性能优化:通过读写分离提升系统整体性能

💡 实际场景引入

场景一:读请求压力过大

问题描述:某电商平台的读请求量是写请求的100倍,单个从库无法承受如此大的读压力,查询响应时间逐渐增加。

你的任务:如何通过增加读节点解决读压力问题?

场景二:读节点故障处理

问题描述:某系统有10个读节点,其中一个读节点故障后,负载均衡器仍然将请求分发到该节点,导致部分请求失败。

你的任务:如何实现读节点的自动故障检测和转移?


读写分离是MySQL扩展性架构中的重要组成部分,通过将读操作和写操作分发到不同的数据库实例,可以显著提升系统的并发处理能力和可用性。随着业务规模的增长,从简单的主从架构演进到支持数十个读节点的复杂架构,需要考虑负载均衡、数据一致性、故障处理等多个方面。本节将深入探讨读写分离的架构演进过程,分享从单点到30个读节点的实践经验。

读写分离基本架构

传统主从架构

最简单的读写分离架构是单一主库配一个或多个从库:

应用层

负载均衡器

主库-写操作

从库1-读操作

数据同步

# 主库配置 [mysqld] server-id = 1 log-bin = mysql-bin binlog-format = ROW sync_binlog = 1 # 从库配置 [mysqld] server-id = 2 relay-log = relay-bin read_only = 1

应用层实现读写分离

// 基于注解的读写分离实现@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public@interfaceReadOnly{}// 数据源路由publicclassDataSourceRouting{privatestaticfinalThreadLocal<String>contextHolder=newThreadLocal<>();publicstaticvoidsetWrite(){contextHolder.set("write");}publicstaticvoidsetRead(){contextHolder.set("read");}publicstaticStringgetDataSource(){returncontextHolder.get();}publicstaticvoidclear(){contextHolder.remove();}}// 数据源配置@ConfigurationpublicclassDataSourceConfig{@Bean@PrimarypublicDataSourceroutingDataSource(){RoutingDataSourceroutingDataSource=newRoutingDataSource();Map<Object,Object>dataSourceMap=newHashMap<>();dataSourceMap.put("write",writeDataSource());dataSourceMap.put("read",readDataSource1());dataSourceMap.put("read1",readDataSource1());dataSourceMap.put("read2",readDataSource2());routingDataSource.setTargetDataSources(dataSourceMap);routingDataSource.setDefaultTargetDataSource(writeDataSource());returnroutingDataSource;}}// AOP切面实现自动路由@Aspect@ComponentpublicclassDataSourceAspect{@Before("@annotation(readOnly)")publicvoidsetReadDataSourceType(ReadOnlyreadOnly){DataSourceRouting.setRead();}@Before("@annotation(org.springframework.transaction.annotation.Transactional)")publicvoidsetWriteDataSourceType(JoinPointpoint){DataSourceRouting.setWrite();}@After("@annotation(readOnly) || @annotation(org.springframework.transaction.annotation.Transactional)")publicvoidclearDataSourceType(){DataSourceRouting.clear();}}

适用场景

读多写少场景

-- 典型的读多写少场景-- 电商商品详情页查询SELECTp.product_name,p.description,p.price,p.stock,b.brand_name,c.category_name,AVG(r.rating)asavg_rating,COUNT(r.review_id)asreview_countFROMproducts pJOINbrands bONp.brand_id=b.brand_idJOINcategories cONp.category_id=c.category_idLEFTJOINproduct_reviews rONp.product_id=r.product_idWHEREp.product_id=12345GROUPBYp.product_id;

报表查询场景

-- 大量数据分析查询SELECTDATE(o.created_at)asorder_date,COUNT(*)asorder_count,SUM(o.total_amount)astotal_amount,AVG(o.total_amount)asavg_amountFROMorders oWHEREo.created_at>=DATE_SUB(NOW(),INTERVAL30DAY)GROUPBYDATE(o.created_at)ORDERBYorder_dateDESC;

缓存预热场景

// 缓存预热读取大量数据@ServicepublicclassCacheWarmupService{@ReadOnlypublicvoidwarmupProductCache(){intoffset=0;intlimit=1000;while(true){List<Product>products=productRepository.findProducts(offset,limit);if(products.isEmpty()){break;}// 将数据加载到缓存products.forEach(product->{redisTemplate.opsForValue().set("product:"+product.getId(),product,Duration.ofHours(1));});offset+=limit;}}}

读写分离的高可用机制

1. 读节点故障检测与剔除

// 读节点健康检查@ComponentpublicclassReadNodeHealthChecker{privatefinalMap<String,DataSource>readDataSources;privatefinalSet<String>unhealthyNodes=ConcurrentHashMap.newKeySet();@Scheduled(fixedRate=5000)// 每5秒检查一次publicvoidcheckHealth(){readDataSources.forEach((name,dataSource)->{if(isHealthy(dataSource)){unhealthyNodes.remove(name);}else{unhealthyNodes.add(name);log.warn("Read node {} is unhealthy",name);}});}privatebooleanisHealthy(DataSourcedataSource){try(Connectionconn=dataSource.getConnection();PreparedStatementstmt=conn.prepareStatement("SELECT 1");ResultSetrs=stmt.executeQuery()){returnrs.next();}catch(SQLExceptione){returnfalse;}}publicbooleanisNodeHealthy(StringnodeName){return!unhealthyNodes.contains(nodeName);}}

2. 自动故障转移

// 智能数据源选择publicclassSmartRoutingDataSourceextendsAbstractRoutingDataSource{@AutowiredprivateReadNodeHealthCheckerhealthChecker;@OverrideprotectedObjectdetermineCurrentLookupKey(){StringdataSourceKey=DataSourceRouting.getDataSource()
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 23:39:26

【小程序毕设源码分享】基于springboot+小程序的四六级学习小程序或微信小程序的单词学习系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/10/9 19:09:15

【小程序毕设全套源码+文档】基于微信小程序的高校素拓分管理系统(素质拓展活动报名小程序)设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/10/16 10:28:21

从图的视角看 RAG:GraphRAG 的工作方式与思考

&#x1f43c; 概要 这篇文章是写给对检索增强生成 (Retrieval-Augmented Generation, RAG) 技术感兴趣&#xff0c;并希望了解一些新方法的初学者。 我们可能都用过检索增强生成 (RAG)&#xff0c;它在文档里查找具体答案时很方便。但如果我们的问题更大一些&#xff0c;比如“…

作者头像 李华
网站建设 2026/10/7 15:09:49

量子威胁升级:Grover算法对加密模型的颠覆性挑战

随着量子计算商用进程加速&#xff0c;Grover算法对对称加密体系的威胁已从理论走向实践。本文结合量子攻击模拟工具原理&#xff0c;为软件测试从业者提供可落地的抗性评估框架&#xff0c;涵盖测试场景构建、风险量化及防御验证方案。 一、Grover算法的测试核心逻辑 二次加速…

作者头像 李华
网站建设 2026/10/16 5:10:28

GPT-4o 终于要“下线”了

OpenAI 在 2026 年 1 月 29 日发了一则产品公告&#xff1a; 2026 年 2 月 13 日起&#xff0c;ChatGPT 会正式下线一批老模型——GPT-4o、GPT-4.1、GPT-4.1 mini、OpenAI o4-mini&#xff1b;在这一天下线的还有之前宣布的 GPT-5&#xff08;Instant 和 Thinking&#xff09;。…

作者头像 李华