文章目录
-
- [一、 MySQL:稳如磐石的库表设计](#一、 MySQL:稳如磐石的库表设计)
-
- [1.1 库表设计原则](#1.1 库表设计原则)
- [1.2 索引设计(B+树的艺术)](#1.2 索引设计(B+树的艺术))
- [1.3 设计示例与可视化](#1.3 设计示例与可视化)
- [二、 Elasticsearch:海量数据的索引设计](#二、 Elasticsearch:海量数据的索引设计)
-
- [2.1 索引与 Mapping 设计](#2.1 索引与 Mapping 设计)
- [2.2 数据同步流程](#2.2 数据同步流程)
- [三、 Redis:极速缓存的 Key 设计](#三、 Redis:极速缓存的 Key 设计)
-
- [3.1 Key 设计规范](#3.1 Key 设计规范)
- [3.2 数据结构选型思维导图](#3.2 数据结构选型思维导图)
- [四、 RabbitMQ:异步解耦的 Topic 设计](#四、 RabbitMQ:异步解耦的 Topic 设计)
-
- [4.1 Exchange 与 Topic 设计](#4.1 Exchange 与 Topic 设计)
- [4.2 消息模型时序图](#4.2 消息模型时序图)
- 综合架构示意图
在现代高并发、分布式的后端架构中,单一的数据库早已无法满足所有需求。MySQL 负责核心事务与数据持久化,Elasticsearch (ES) 解决海量数据的复杂搜索与分析,Redis 承担极速缓存与计数,而 RabbitMQ (RMQ) 则负责系统解耦与削峰填谷。
本文将深入探讨这四大组件在"库表、索引、Key、Topic"层面的设计规范与最佳实践。
一、 MySQL:稳如磐石的库表设计
MySQL 是数据的"最后一道防线"。设计的目标是:保证数据一致性、扩展性及查询效率。
1.1 库表设计原则
- 命名规范 :使用小写字母、下划线分隔(snake_case)。如
db_order、t_order_detail。 - 字符集 :无脑选择
utf8mb4,兼容 Emoji 和生僻字。 - 主键策略 :
- 尽量避免 UUID(导致聚簇索引碎片)。
- 推荐使用自增
BIGINT,既有序又保证全局唯一。
- 字段类型 :
- 金额使用
DECIMAL,禁止用FLOAT/DOUBLE。 - 状态值用
TINYINT,并备注状态含义(如0:待支付 1:已支付)。 - 时间统一使用
DATETIME或BIGINT(时间戳)。
- 金额使用
1.2 索引设计(B+树的艺术)
- 最左前缀原则 :联合索引
(a, b, c),查询(a, b)走索引,查询(b, c)不走。 - 覆盖索引:查询字段尽量包含在索引中,避免回表(Select * 是大忌)。
1.3 设计示例与可视化
has
1 n User
+bigint id PK
+varchar username
+varchar mobile UK
+datetime create_time
Order
+bigint id PK
+bigint user_id IDX
+decimal amount
+tinyint status
SQL 源码示例:
sql
CREATE TABLE `t_order_base` (
`id` BIGINT UNSIGNED NOT NULL COMMENT '主键ID(雪花算法)',
`user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID',
`order_no` VARCHAR(64) NOT NULL COMMENT '业务订单号',
`total_amount` DECIMAL(10, 2) NOT NULL DEFAULT '0.00' COMMENT '订单总金额',
`status` TINYINT UNSIGNED NOT NULL DEFAULT '0' COMMENT '状态:0-待支付, 10-已支付, 20-已发货',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_no` (`order_no`),
INDEX `idx_user_status` (`user_id`, `status`) COMMENT '用户状态联合索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单基础表';
二、 Elasticsearch:海量数据的索引设计
ES 是基于 Lucene 的分布式搜索引擎,核心在于 倒排索引 。设计重心在于 Mapping 结构 和 分片策略。
2.1 索引与 Mapping 设计
- 索引命名 :
业务_模块_版本,例如mall_goods_v1。通常配合Alias(别名)使用,实现零停机索引切换。 - Keyword vs Text :
Keyword:不分词,用于精确匹配(ID、状态)、聚合、排序。Text:分词,用于全文检索(商品名称、文章内容)。
- 分片 (Shards) :
- 单个分片建议控制在 30GB - 50GB。
- 一旦创建,主分片数不可改(除非 Reindex)。
2.2 数据同步流程
MySQL 到 ES 的数据同步是常见场景,通常采用 Canal 监听 Binlog。
Binlog
Parse
Consume
Bulk Insert
MySQL DB
Canal Server
Kafka/RocketMQ
同步服务
Elasticsearch
Mapping JSON 示例:
json
PUT /mall_goods_v1
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"sku_id": { "type": "keyword" },
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
},
"price": { "type": "double" },
"category_id": { "type": "keyword" },
"tags": { "type": "keyword" }
}
}
}
三、 Redis:极速缓存的 Key 设计
Redis 是基于内存的 KV 数据库。设计核心在于 Key 的命名空间管理 和 Value 的数据结构选择。
3.1 Key 设计规范
- 格式 :
业务线:模块:对象:ID,使用冒号分隔。- Bad :
count,order123 - Good :
mall:order:count:u_8821,sys:session:id_x99
- Bad :
- 长度:不要太长,节省内存;也不要太短,保证可读性。
- 大 Key 问题:避免 Hash/List/Set 中元素超过 5000 个,容易阻塞主线程。
3.2 数据结构选型思维导图
Redis Key 选型
String
简单的 KV 缓存
SETNX
INCR
Hash
User Profile
SkuID: Count
减少 Key 的数量
List
LPUSH/RPOP
最新 N 条评论
Set
点赞用户
SINTER
ZSet
Score: 分数
Score: 时间戳
Bitmap
用户签到
在线状态
Python (redis-py) 示例:
python
import redis
r = redis.Redis(host='localhost', port=6379, db=0)
# 场景:缓存商品详情,1小时过期
key = "mall:goods:detail:10086"
value = '{"id": 10086, "name": "iPhone 16"}'
r.set(key, value, ex=3600)
# 场景:商品销量排行榜
rank_key = "mall:goods:rank:daily"
r.zincrby(rank_key, 1, "sku_10086")
四、 RabbitMQ:异步解耦的 Topic 设计
RabbitMQ 是基于 AMQP 协议的消息中间件。设计核心在于 Exchange 类型选择 和 Topic 路由键设计。
4.1 Exchange 与 Topic 设计
- Exchange 类型 :
Direct:精确匹配,简单路由。Topic:模式匹配,灵活性最强(推荐)。Fanout:广播,不处理路由键。
- Routing Key 命名 :
业务.来源.动作.状态。- 示例:
order.mobile.create.success、user.web.login.failed。 - 优势:消费者可以使用
order.#(监听所有订单消息) 或*.mobile.*.*(监听所有移动端消息)。
- 示例:
4.2 消息模型时序图
下图展示了一个基于 Topic Exchange 的订单处理流程:
Queue (通知服务) Queue (库存服务) Exchange (Topic: mall.event) 生产者 (OrderService) Queue (通知服务) Queue (库存服务) Exchange (Topic: mall.event) 生产者 (OrderService) RoutingKey: order.created Binding: order.* Binding: 发送消息 "Order 路由消息 路由消息 扣减库存 发送短信/邮件
Java (Spring Boot) 配置示例:
java
@Configuration
public class RabbitConfig {
public static final String TOPIC_EXCHANGE = "mall.event.exchange";
public static final String STOCK_QUEUE = "stock.order.queue";
// 1. 定义 Topic 交换机
@Bean
public TopicExchange exchange() {
return new TopicExchange(TOPIC_EXCHANGE);
}
// 2. 定义队列
@Bean
public Queue stockQueue() {
return new Queue(STOCK_QUEUE);
}
// 3. 绑定:库存队列关心所有订单事件 (order.*)
@Bean
public Binding bindingStock() {
return BindingBuilder.bind(stockQueue())
.to(exchange())
.with("order.*"); // 路由键匹配模式
}
}
一个优秀的后端系统,能够充分利用这四者的长处:
- MySQL:作为 Truth of Source,记录核心业务数据,不求快但求稳。
- Redis:作为前置缓存,抗住 90% 的读流量,保护数据库。
- Elasticsearch:作为查询引擎,处理复杂的多条件筛选和文本检索。
- RabbitMQ:作为血管,连接各个微服务,确保写入操作的最终一致性。
综合架构示意图
读
Miss
写
事务写
异步消息
解耦
写入
复杂搜索
主从复制
用户
API Gateway
Redis
业务服务
MySQL Master
RabbitMQ
索引服务
Elasticsearch
MySQL Slave
通过合理规范库表、索引、Key 和 Topic 的设计,我们不仅能提升系统的性能,更能极大地降低后期的维护成本和沟通成本。