【架构实战】RDS多表复杂检索极慢:基于Flink CDC与ES的流式读写分离解法
在业务初期,一张包含上百个字段的 orders 表加上几个 B+ 树索引就能满足查询需求。但随着业务复杂化,前端页面出现了“商品名模糊匹配 + 时间范围 + 多个可选状态”的超级组合筛选器。此时 MySQL 的最左前缀匹配原则彻底失效,优化器被迫走全表扫描,RDS 实例的 CPU 瞬间打满 100%。
标准的架构级工程解法是:CQRS(命令查询职责分离)。让 MySQL 专心处理事务性写入,将复杂的倒排索引与多维组合检索任务,实时平滑地卸载给 Elasticsearch (ES)。
1. 摒弃传统中间件,引入 Flink CDC 实时流计算
传统方案通常依赖 Canal -> Kafka -> Logstash -> ES 这样极其冗长的链路,极易发生丢数据或延迟飙升。现代云原生架构推荐直接使用 Flink CDC。它能够无锁读取 MySQL 全量历史数据,并自动无缝切换到 Binlog 增量读取,一套架构搞定“全量+增量”同步。
2. 极简的 Flink SQL 声明式同步管线
无需编写复杂的 Java 拓扑代码,直接在 Flink 平台上提交 Flink SQL。第一步,将 RDS 映射为一张流表:
-- 1. 定义源端 MySQL CDC 流表
CREATE TABLE mysql_orders (
id INT,
order_no STRING,
user_name STRING,
order_status INT,
create_time TIMESTAMP(3),
PRIMARY KEY (id) NOT ENFORCED
) WITH (
'connector' = 'mysql-cdc',
'hostname' = 'rds.intranet.myhuaweicloud.com',
'port' = '3306',
'username' = 'sync_user',
'password' = 'SyncPassword#123',
'database-name' = 'business_db',
'table-name' = 'orders'
);
第二步,映射目标端的 ES 索引表,并用一条 INSERT 语句打通底层的高并发数据搬运链路:
-- 2. 定义目标端 Elasticsearch 表
CREATE TABLE es_orders (
id INT,
order_no STRING,
user_name STRING,
order_status INT,
create_time TIMESTAMP(3),
PRIMARY KEY (id) NOT ENFORCED
) WITH (
'connector' = 'elasticsearch-7',
'hosts' = 'http://es.intranet.myhuaweicloud.com:9200',
'index' = 'orders_idx'
);
-- 3. 启动实时同步任务,Flink 底层自动处理 Exactly-Once 语义与并发写入
INSERT INTO es_orders SELECT * FROM mysql_orders;
3. API 层流量双写路由切换
同步链路建立且数据追平后,在后端的微服务网关或 DAO 层代码中,进行数据源路由改造:
-
所有
INSERT、UPDATE、DELETE强事务请求,以及根据主键ID的点查,继续打入 MySQL。 -
所有复杂的分页列表查询、文本模糊匹配,全部改写为 DSL 语句打入 Elasticsearch 集群。
总结: 关系型数据库不是万能的“大胃王”。通过引入 Flink CDC 与 ES 搭建亚秒级的异构数据同步管线,我们在不入侵核心事务代码逻辑的前提下,利用底层存储引擎各自的强项(MySQL 的 ACID 与 ES 的倒排索引),构建出了极具扩展性的企业级高并发数据底座。
- 点赞
- 收藏
- 关注作者
评论(0)