阶段10: 迭代与扩展
目标: 添加新功能(搜索/邮件/评价),反思知识图谱,选择下一个项目继续练习。
| 模块 | 内容 |
|---|---|
| Module 3 | 复制(数据库读写分离、主从同步) |
| Module 5 | 消息队列(异步任务、解耦、削峰) |
| Module 9 | CQRS(命令查询职责分离) |
| Module 11 | 微服务(服务拆分、通信、一致性) |
步骤 1:添加全文搜索
Section titled “步骤 1:添加全文搜索”引入 Elasticsearch 替代数据库 LIKE 查询。
请帮我为酒店预订系统添加 Elasticsearch 全文搜索:
1. docker-compose 添加 Elasticsearch: - image: elasticsearch:8.11.0 - 单节点模式(discovery.type=single-node) - 关闭安全认证(开发环境:xpack.security.enabled=false) - 内存限制:ES_JAVA_OPTS=-Xms512m -Xmx512m - volumes: es_data:/usr/share/elasticsearch/data
2. 创建索引 hotel_rooms: - 字段映射: - name: text(中文分词器 ik_max_word) - city: keyword - address: text - description: text(中文分词器) - room_type: keyword - price: float - amenities: keyword(数组) - available: boolean - location: geo_point(经纬度,支持附近搜索)
3. 数据同步方案: - 初始化:写一个同步脚本,把 PostgreSQL 的房间数据全量导入 ES - 增量同步:房间信息变更时(创建/更新/删除),同步更新 ES - 用 GORM Hook(AfterCreate/AfterUpdate/AfterDelete)触发同步 - 同步失败不影响主流程(异步 + 重试)
4. 搜索 API 改造: - GET /api/search → 查 ES 而非 PostgreSQL - 支持:关键词搜索、城市筛选、价格区间、日期可用性、按距离排序 - 搜索结果高亮(匹配关键词标红) - 分页 + 排序(价格/评分/距离)
5. 引入 Go 的 ES 客户端(olivere/elastic 或官方 go-elasticsearch)
给出完整的 ES 索引配置、同步代码和搜索 API 代码。步骤 2:添加真实邮件通知
Section titled “步骤 2:添加真实邮件通知”用邮件服务发送预订确认和取消通知。
请帮我为酒店预订系统添加邮件通知功能:
1. 选择邮件服务:Resend(推荐,API 简单)或 SendGrid - 注册账号,获取 API Key - 配置发件域名(或用默认沙箱域名测试)
2. 邮件模板(HTML): - 预订确认邮件: - 标题:您的预订已确认 - [酒店名称] - 内容:预订编号、酒店名、房型、入住/离店日期、总价、取消政策 - 预订取消邮件: - 标题:预订已取消 - [预订编号] - 内容:预订编号、取消时间、退款信息 - 入住提醒邮件(入住前一天): - 标题:明日入住提醒 - [酒店名称] - 内容:入住时间、地址、联系电话
3. 异步发送: - 邮件发送放入 goroutine,不阻塞主流程 - 发送失败重试 3 次,间隔 1s/5s/30s - 记录发送日志(成功/失败/重试) - 后续可替换为消息队列(Redis/RabbitMQ)
4. 配置: - .env 添加 RESEND_API_KEY - 开发环境可以只打印日志不真发邮件(dry run)
给出完整的邮件服务代码、模板和集成代码。步骤 3:添加评价系统
Section titled “步骤 3:添加评价系统”完成入住后可以评价酒店。
请帮我为酒店预订系统添加评价功能:
1. 数据模型(reviews 表): - id, booking_id(关联预订,一个预订只能评价一次) - user_id, hotel_id, room_id - rating(1-5 整数) - content(评价文本,最长 1000 字) - images(评价图片 URL 数组,最多 5 张) - created_at - 约束:booking 状态必须是 checked_out 才能评价
2. API: - POST /api/bookings/:id/review — 提交评价 - GET /api/hotels/:id/reviews — 获取酒店评价(分页,按时间倒序) - GET /api/hotels/:id/rating — 获取酒店平均分和评分分布
3. 平均分计算(最终一致性): - 方案A(简单):每次查询时 AVG(rating),小数据量可行 - 方案B(推荐):hotels 表加 avg_rating 和 review_count 字段 - 新评价提交后,异步更新 avg_rating - 用 goroutine 或消息队列 - 短暂不一致可以接受(最终一致性) - 给出两种方案的代码,默认用方案B
4. 前端: - 预订详情页显示"写评价"按钮(仅 checked_out 状态) - 评价表单:星级选择 + 文本输入 - 酒店详情页显示评价列表和平均分
给出完整的 model、handler、前端组件代码。步骤 4:读写分离(概念设计)
Section titled “步骤 4:读写分离(概念设计)”理解 CQRS 和读写分离,画架构图,不实施。
假设酒店预订系统流量增长 100 倍,搜索请求远多于预订请求。请帮我设计读写分离方案:
1. 当前瓶颈分析: - 搜索查询(读)和预订操作(写)共用一个 PostgreSQL - 写操作需要事务和锁(预订冲突检测) - 读操作需要复杂查询(搜索、筛选、排序) - 读写互相影响性能
2. 读写分离方案: - 写库:PostgreSQL 主库,处理预订/取消/评价 - 读库:PostgreSQL 只读副本 + Elasticsearch - 同步:主库 → WAL → 从库(异步复制) - 搜索走 ES,详情走从库,预订走主库
3. CQRS 方案(进阶): - Command(写):预订服务 → 主库 → 发布事件 - Query(读):搜索服务 → ES/Redis - 事件驱动同步:预订事件 → 消息队列 → 更新 ES 索引 - 最终一致性:写入后搜索结果可能延迟几秒更新
4. 请画出架构图(文本格式),标注: - 数据流方向 - 各组件职责 - 一致性策略 - 适用场景
注意:这一步只做设计,不实施代码。目的是理解读写分离和 CQRS 的思路。步骤 5:反思与知识图谱
Section titled “步骤 5:反思与知识图谱”回顾全部知识点,画全景图。
我已经完成了酒店预订系统(Hotel Reservation)从 0 到 1 的全部开发。请帮我做一次全面反思:
1. 知识图谱梳理——按阶段列出我用到的所有知识点: - 阶段1(需求):用户故事、ER 图、API 设计、状态机 - 阶段2(数据库):PostgreSQL、GORM、索引、事务 - 阶段3(核心功能):CRUD、JWT、中间件、并发控制 - 阶段4(缓存):Redis、缓存策略、缓存失效 - 阶段5(前端):React、路由、状态管理、API 调用 - 阶段6(安全):OWASP Top 10、输入校验、限流 - 阶段7(测试):单元/集成/E2E、CI - 阶段8(部署):Docker、Caddy、HTTPS、CI/CD - 阶段9(监控):日志、指标、Grafana、告警、SLO - 阶段10(扩展):ES、邮件、评价、CQRS
2. 画一张 Hotel Reservation 全景图(文本格式): - 用户请求 → Caddy → Go API → PostgreSQL/Redis/ES - 标注每个组件用到的技术和知识点
3. 自我评估: - 哪些知识点我已经理解透彻? - 哪些只是"用了"但不理解原理? - 哪些在实际工作中最可能用到?
4. 记录 3 个"我踩过的最深的坑"和解决方案
请用 Markdown 表格和文本架构图呈现。步骤 6:换系统练习
Section titled “步骤 6:换系统练习”选择新项目,重走阶段 1-9。
我已经完成了 Hotel Reservation 项目,现在想选一个新系统练习。请帮我分析以下选项:
选项 A:Chat System(即时通讯)- 新知识点:WebSocket、在线状态、消息存储、消息队列- 技术栈:Go + WebSocket + Redis Pub/Sub + PostgreSQL- 难度:中高(实时通信是新挑战)- 与酒店系统的重叠:用户系统、JWT、部署
选项 B:E-commerce(电商系统)- 新知识点:购物车、库存扣减、支付集成、订单状态机- 技术栈:Go + PostgreSQL + Redis + 支付 API- 难度:中(业务逻辑复杂但技术栈熟悉)- 与酒店系统的重叠:预订≈下单、库存≈房间可用性
选项 C:URL Shortener(短链接服务)- 新知识点:高并发读、分布式 ID、301/302 重定向、统计分析- 技术栈:Go + Redis + PostgreSQL- 难度:中低(功能简单但性能要求高)- 与酒店系统的重叠:较少,侧重不同
请帮我:1. 对比三个选项的学习收益2. 推荐一个最适合作为第二个项目的选项3. 给出选定项目的"阶段1:需求分析"的 prompt,让我可以直接开始- Elasticsearch 已集成,搜索走 ES 而非数据库 LIKE
- 邮件通知已接入,预订确认/取消会发邮件
- 评价系统已完成,酒店有平均分和评价列表
- 读写分离架构图已画出(概念理解,不实施)
- 知识图谱已梳理,全景架构图已画出
- 已选定下一个练习项目并开始阶段 1
-
Elasticsearch 中文分词不生效: 默认的 standard 分词器不支持中文(会按字拆分)。必须安装 ik 分词器插件,并在索引映射中指定
analyzer: "ik_max_word"。Docker 中安装插件:elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v8.11.0/elasticsearch-analysis-ik-8.11.0.zip。 -
数据同步丢失: GORM Hook 里调用 ES 同步,如果 ES 挂了或网络超时,同步就丢了。生产环境应该用消息队列(先写消息再消费同步),保证至少一次投递。开发阶段可以先用 Hook + 重试,但要知道这不是最终方案。
-
邮件发送拖慢接口: 即使放在 goroutine 里,如果邮件 API 超时(比如 30 秒),大量 goroutine 堆积会耗尽内存。要设置 HTTP 客户端超时(5 秒),并限制并发 goroutine 数量(用 channel 做信号量或用 worker pool)。
-
评价平均分不一致: 用异步更新 avg_rating 时,如果两个评价几乎同时提交,可能出现竞态条件。用
UPDATE hotels SET avg_rating = (SELECT AVG(rating) FROM reviews WHERE hotel_id = ?) WHERE id = ?而不是在应用层计算后 SET,让数据库保证原子性。