Furria
Furria 是一个面向 UGC 场景的社交平台后端(附 Next.js 前端)。
项目围绕真实互联网后端中的分布式设计问题展开,采用领域拆分和事件驱动架构,重点处理服务边界、最终一致性、热点数据写入、关注流构建以及系统可观测性。
项目规模:
- 7 个 Go 服务
- 每服务独立 PostgreSQL
- Kafka 事件总线驱动多个异步消费者
- 支持 Docker Compose / Kubernetes 部署
Why
社交能力的瓶颈并不相同:鉴权要安全边界,关系是图查询,内容互动是写放大,Feed 偏读组装,搜索是最终一致投影。
在业务规模增长后,不同领域会呈现不同的数据模型、访问模式和扩展需求。将所有能力集中在单体数据库中,会增加模块间耦合,并限制独立演进。Furria 按 数据归属、访问模式、故障隔离 划边界;跨域只走领域事件或内部 API,禁止直连别的领域表。
拆分目标不是增加服务数量,而是建立清晰的数据归属和故障边界;能够保持一致性的地方不强行拆分,需要独立扩展的能力才进行隔离。
Architecture
同步写路径与异步投影分开:
Client
|
Kong Gateway
|
+-------------+-------------+
| | |
identity community feed
| |
PostgreSQL PostgreSQL
|
Outbox
|
Kafka
+----------+----------+
| | |
feed search notification
indexer
发帖只对 community 库强一致;Feed / 搜索 / 通知是下游最终一致投影,发布接口不串行等待它们。
Service Boundary
| 服务 | 职责 | 拆分原因 |
|---|---|---|
| identity | OAuth、会话、资料、封禁/删除 | 安全与用户生命周期独立 |
| relation | 关注、拉黑 | 图查询与扇出,和内容写入模式不同 |
| community | 帖子、评论、互动 | 核心写路径与计数优化单独扩展 |
| feed | 关注流 inbox / 组装 / 游标 | 读侧计算与发帖解耦,避免拖慢发布 |
| notification | 通知落库 + SSE | 长连接数量与业务请求隔离;SSE 生命周期独立管理 |
| search-api / search-indexer | 查询转发 / 事件建索引 | 索引是投影;搜索故障不阻塞发帖 |
Key Design
主要工程设计如下。细节与 trade-off 见链接文档。
Transactional Outbox
业务变更与 outbox 同事务提交,Relay 异步投递 Kafka,避免「库成功、消息丢了」。
代价:下游最终一致;消费端必须幂等。
关注 Feed
根据用户影响力选择 push、pull 或混合模式,避免大规模粉丝关系导致写放大。读路径:采集 → 过滤 → 排序 → 游标。
→ Feed 设计
热点互动计数
点赞关系落 Postgres;展示计数走 Redis bump + dirty,flusher ClaimDirty 批量回写。Redis 不是点赞关系的事实存储,而是计数展示和热点缓冲层。
失败:bump 失败释放 claim → 消息重试;超限进 DLQ,避免堵死消费。
→ 互动计数一致性
搜索索引
indexer 只消费事件写 Meilisearch;search-api 只做查询。检索与内容库故障域分离。
Engineering Practice
- 契约: Protobuf + Buf(lint / breaking),内部 gRPC
- 平台层: Outbox、消息、超时/熔断、指标与 tracing 复用
- CI: 按 diff 的 affected 检测,避免无关服务空跑
- 可观测: Prometheus + OpenTelemetry(本地 Jaeger / 集群 Tempo)
- 部署: Compose 本地依赖;Kubernetes manifests 单集群部署
网关、mesh 与搜索引擎是工程配套能力,业务边界仍由领域服务与事件定义。
面试准备材料:docs/interview/
Tech Stack
核心: Go、gRPC、Protobuf、PostgreSQL、Redis、Kafka
工程: Kubernetes、Docker、OpenTelemetry、Prometheus
辅助: Gin、GORM、Wire、Kong、Istio、Meilisearch、MinIO、Next.js
Deployment
提供 Docker Compose 与 Kubernetes manifests,支持本地开发环境和单集群部署。本地联调命令见 docs/DEVELOPMENT.md。