跳转到内容

阶段10: 迭代与扩展

目标: 添加新功能(搜索/邮件/评价),反思知识图谱,选择下一个项目继续练习。

模块内容
Module 3复制(数据库读写分离、主从同步)
Module 5消息队列(异步任务、解耦、削峰)
Module 9CQRS(命令查询职责分离)
Module 11微服务(服务拆分、通信、一致性)

引入 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 代码。

用邮件服务发送预订确认和取消通知。

请帮我为酒店预订系统添加邮件通知功能:
1. 选择邮件服务:Resend(推荐,API 简单)或 SendGrid
- 注册账号,获取 API Key
- 配置发件域名(或用默认沙箱域名测试)
2. 邮件模板(HTML):
- 预订确认邮件:
- 标题:您的预订已确认 - [酒店名称]
- 内容:预订编号、酒店名、房型、入住/离店日期、总价、取消政策
- 预订取消邮件:
- 标题:预订已取消 - [预订编号]
- 内容:预订编号、取消时间、退款信息
- 入住提醒邮件(入住前一天):
- 标题:明日入住提醒 - [酒店名称]
- 内容:入住时间、地址、联系电话
3. 异步发送:
- 邮件发送放入 goroutine,不阻塞主流程
- 发送失败重试 3 次,间隔 1s/5s/30s
- 记录发送日志(成功/失败/重试)
- 后续可替换为消息队列(Redis/RabbitMQ)
4. 配置:
- .env 添加 RESEND_API_KEY
- 开发环境可以只打印日志不真发邮件(dry run)
给出完整的邮件服务代码、模板和集成代码。

完成入住后可以评价酒店。

请帮我为酒店预订系统添加评价功能:
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、前端组件代码。

理解 CQRS 和读写分离,画架构图,不实施。

假设酒店预订系统流量增长 100 倍,搜索请求远多于预订请求。请帮我设计读写分离方案:
1. 当前瓶颈分析:
- 搜索查询(读)和预订操作(写)共用一个 PostgreSQL
- 写操作需要事务和锁(预订冲突检测)
- 读操作需要复杂查询(搜索、筛选、排序)
- 读写互相影响性能
2. 读写分离方案:
- 写库:PostgreSQL 主库,处理预订/取消/评价
- 读库:PostgreSQL 只读副本 + Elasticsearch
- 同步:主库 → WAL → 从库(异步复制)
- 搜索走 ES,详情走从库,预订走主库
3. CQRS 方案(进阶):
- Command(写):预订服务 → 主库 → 发布事件
- Query(读):搜索服务 → ES/Redis
- 事件驱动同步:预订事件 → 消息队列 → 更新 ES 索引
- 最终一致性:写入后搜索结果可能延迟几秒更新
4. 请画出架构图(文本格式),标注:
- 数据流方向
- 各组件职责
- 一致性策略
- 适用场景
注意:这一步只做设计,不实施代码。目的是理解读写分离和 CQRS 的思路。

回顾全部知识点,画全景图。

我已经完成了酒店预订系统(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 表格和文本架构图呈现。

选择新项目,重走阶段 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

  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

  2. 数据同步丢失: GORM Hook 里调用 ES 同步,如果 ES 挂了或网络超时,同步就丢了。生产环境应该用消息队列(先写消息再消费同步),保证至少一次投递。开发阶段可以先用 Hook + 重试,但要知道这不是最终方案。

  3. 邮件发送拖慢接口: 即使放在 goroutine 里,如果邮件 API 超时(比如 30 秒),大量 goroutine 堆积会耗尽内存。要设置 HTTP 客户端超时(5 秒),并限制并发 goroutine 数量(用 channel 做信号量或用 worker pool)。

  4. 评价平均分不一致: 用异步更新 avg_rating 时,如果两个评价几乎同时提交,可能出现竞态条件。用 UPDATE hotels SET avg_rating = (SELECT AVG(rating) FROM reviews WHERE hotel_id = ?) WHERE id = ? 而不是在应用层计算后 SET,让数据库保证原子性。