2. 技术选型与架构设计:后端框架选择、消息队列选型、数据库设计原则
好,咱们进入第二章。这一章说白了,就是决定整个消息通知模块的「骨架」该怎么搭。我见过不少项目,一开始没想清楚技术选型,结果后面改得痛不欲生。所以这一章,咱们把后端框架、消息队列、数据库设计这几个核心问题,一次性聊透。
2.1 后端框架选择:Django 还是 Flask?
这个问题,几乎每个做 Python 后端的人都会纠结。我个人习惯是这么判断的:项目规模大、团队人多、需要快速出活,选 Django;项目轻量、高度定制、追求极致性能,选 Flask。
拿咱们这个 OA 系统消息通知模块来说,我建议选 Django。为什么?
- 自带 Admin 后台:消息记录、模板管理、用户配置,直接开箱即用。我记得之前用 Flask 做类似功能,光写个后台管理页面就花了两天。
- ORM 成熟稳定:咱们要处理用户、消息、通知记录这些复杂关系,Django ORM 的关联查询、事务支持都非常顺手。
- 中间件机制:消息鉴权、日志记录、频率限制,都可以通过中间件优雅实现。
当然,Django 也不是没缺点。它比较「重」,启动慢,ORM 有时候会生成一些奇怪的 SQL。但说实话,对于 OA 系统这种企业级应用,这点代价完全可以接受。
2.2 消息队列选型:Redis 还是 RabbitMQ?
消息队列,是消息通知模块的「心脏」。选错了,后面会非常难受。
咱们先看两个选项的特点:
| 特性 | Redis | RabbitMQ |
|---|---|---|
| 定位 | 内存数据库,支持消息队列 | 专业消息中间件 |
| 消息持久化 | 支持(但性能有损耗) | 原生支持,可靠性高 |
| 消息确认机制 | 无原生 ACK | 支持 ACK、重试、死信队列 |
| 复杂度 | 简单,学习成本低 | 中等,需要理解 Exchange、Binding 等概念 |
| 适用场景 | 轻量级、高吞吐、允许少量丢消息 | 金融级、必须保证消息不丢、复杂路由 |
我的建议是:优先选 Redis。原因有三:
- OA 系统消息通知,对消息可靠性要求没那么高。偶尔丢一条通知,用户刷新一下页面就看到了,不会造成经济损失。
- Redis 部署简单。很多项目本来就在用 Redis 做缓存,直接复用就行,不用额外维护一套 RabbitMQ 集群。
- 性能足够。Redis 的 List 和 Pub/Sub 模式,处理每秒几千条消息完全没问题。
那什么时候选 RabbitMQ?嗯,如果你要处理跨系统的消息通知,比如 OA 系统要发消息给 ERP、CRM,而且每条消息都必须落地,那 RabbitMQ 更合适。不过咱们这个课程,先以 Redis 为主。
2.3 数据库设计原则
数据库设计,是消息通知模块的「地基」。地基没打好,后面查询慢、扩展难,哭都来不及。
我总结了几条核心原则:
2.3.1 读写分离,按场景设计表
消息通知模块,典型的「写多读少」。用户发一条消息,可能几百上千人读。所以,写操作要快,读操作要灵活。
我一般会设计三张核心表:
- 消息主表(message):存消息的标题、内容、发送时间、发送人等。每条消息只存一次。
- 用户消息关联表(user_message):存哪个用户收到了哪条消息,以及是否已读、是否删除等状态。
- 消息模板表(message_template):存通知模板,比如「您的请假申请已通过」这种固定格式。
你想想看,如果我把用户状态直接塞到消息主表里,那一条消息发 1000 个人,就得存 1000 条重复记录。数据量一上来,查询就炸了。
2.3.2 合理使用索引
索引不是越多越好。我见过有人给每个字段都加了索引,结果写入速度慢得像蜗牛。
对于消息通知模块,重点给这几个字段加索引:
- user_id:用户查自己的消息,这是最频繁的查询。
- is_read:查未读消息时用。
- created_at:按时间排序时用。
2.3.3 考虑数据归档
消息通知数据,增长非常快。一个 500 人的公司,每天发 10 条通知,一年就是 180 万条记录。如果不做归档,数据库迟早扛不住。
我的做法是:按时间分表。比如每个月一张表,或者每季度一张表。查询时根据时间范围路由到对应的表。
嗯,这里要注意,分表之后,跨表查询会变复杂。所以建议在应用层做路由,而不是依赖数据库的联邦查询。
2.3.4 预留扩展字段
消息通知的格式,未来可能会变。比如今天只支持文本,明天要支持图片、链接、甚至小程序卡片。
所以,我习惯在消息主表里加一个 extra_data 字段,类型是 JSON。这样以后加新字段,不用改表结构,直接往 JSON 里塞数据就行。
-- 示例:消息主表结构
CREATE TABLE message (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
sender_id INT NOT NULL,
message_type VARCHAR(50) DEFAULT 'text',
extra_data JSON,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_sender_time (sender_id, created_at)
);
好了,技术选型和架构设计就聊到这儿。下一章,咱们开始动手搭建开发环境,把 Django 项目跑起来。