本章记录小红书从创立到初步成型的技术历程。这个阶段,小红书从一个简单的海外购物指南PDF逐步转型为社区平台,技术团队从零开始构建了支撑百万用户的技术体系。
2013.06 ─────> 2013.12 ─────> 2014.06 ─────> 2015.01 ─────> 2015.12
│ │ │ │ │
创立公司 App上线 社区功能 电商尝试 百万用户
PDF指南 单体架构 UGC内容 福利社上线 架构升级
2013年6月,毛文超和瞿芳在上海创立小红书。最初的产品形态是一份名为《小红书出境购物攻略》的PDF文档,主要面向出境游用户提供购物信息。
初始产品形态演进:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ PDF 1.0 │ --> │ PDF 2.0 │ --> │ App 1.0 │
│ 静态内容 │ │ 交互优化 │ │ 原生应用 │
│ 人工编辑 │ │ 用户反馈 │ │ 动态内容 │
└─────────────┘ └─────────────┘ └─────────────┘
2013.06 2013.09 2013.12
技术决策关键点:
作为一个创业团队,小红书在技术选型上遵循”简单、成熟、快速迭代”的原则:
| 技术层级 | 选择方案 | 选择理由 |
|---|---|---|
| 后端语言 | Python 2.7 | 开发效率高,生态成熟 |
| Web框架 | Django 1.6 | 功能完整,自带Admin |
| 数据库 | MySQL 5.6 | 稳定可靠,社区活跃 |
| 缓存 | Memcached | 简单高效,部署容易 |
| 服务器 | 阿里云ECS | 成本可控,扩展灵活 |
| CDN | 七牛云 | 图片存储专业服务商 |
小红书 App 1.0 架构图 (2013.12)
┌──────────────────────────────────────────┐
│ iOS/Android客户端 │
└──────────────────────────────────────────┘
│
↓ HTTPS
┌──────────────────────────────────────────┐
│ Nginx (负载均衡) │
└──────────────────────────────────────────┘
│
┌───────────┴───────────┐
↓ ↓
┌──────────────┐ ┌──────────────┐
│ Django App │ │ Django App │
│ Server 1 │ │ Server 2 │
└──────────────┘ └──────────────┘
│ │
└───────────┬───────────┘
↓
┌──────────────────────────────────────────┐
│ MySQL (Master-Slave) │
│ Master: 写入 Slave: 读取 │
└──────────────────────────────────────────┘
│
┌──────────────────────────────────────────┐
│ Memcached (缓存层) │
└──────────────────────────────────────────┘
2014年初,小红书意识到仅靠编辑团队产出内容无法满足用户需求,开始转向UGC(用户生成内容)模式。
技术挑战与解决方案:
| 挑战 | 解决方案 | 技术实现 |
|---|---|---|
| 内容存储激增 | 引入对象存储 | 七牛云SDK集成 |
| 图片处理需求 | 图片处理服务 | 七牛云图片处理API |
| 内容审核 | 人工+规则审核 | 关键词过滤+人工审核队列 |
| 用户系统 | 账号体系建设 | Django Auth + 自定义扩展 |
小红书的核心功能”笔记”在这个阶段逐步成型:
# 笔记数据模型示例(简化版)
class Note(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=100)
content = models.TextField()
images = models.JSONField() # 存储图片URL列表
tags = models.ManyToManyField(Tag)
location = models.ForeignKey(Location, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
view_count = models.IntegerField(default=0)
like_count = models.IntegerField(default=0)
class NoteComment(models.Model):
note = models.ForeignKey(Note)
user = models.ForeignKey(User)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
Feed流是社区产品的核心,小红书采用了Pull模式的实现方案:
Feed生成流程:
用户请求Feed
│
↓
获取关注列表
│
↓
查询关注用户的笔记
│
↓
按时间排序
│
↓
返回Feed数据
优化措施:
1. 使用Redis缓存热门笔记
2. 分页加载,每次20条
3. 预加载下一页数据
随着内容量的增长,仅依靠时间线已无法满足内容分发需求。2014年中,小红书开始构建推荐系统。
用户增长与内容增长对比:
内容量(万)
50 ┤ ╱
40 ┤ ╱
30 ┤ ╱
20 ┤ ╱──── 内容增长
10 ┤ ╱────── 用户增长
0 └──┬───┬───┬───┬───┬
Q1'14 Q2'14 Q3'14 Q4'14 Q1'15
第一版推荐系统采用规则+协同过滤的混合策略:
推荐算法流程:
┌─────────────────────────────────────┐
│ 获取用户画像 │
│ (浏览历史、点赞、关注标签) │
└─────────────────────────────────────┘
│
↓
┌─────────────────────────────────────┐
│ 计算内容相似度 │
│ (标签匹配、地理位置、时间) │
└─────────────────────────────────────┘
│
↓
┌─────────────────────────────────────┐
│ 协同过滤 │
│ (用户行为相似度计算) │
└─────────────────────────────────────┘
│
↓
┌─────────────────────────────────────┐
│ 综合排序 │
│ 权重:热度30% + 相关度50% + 新鲜度20% │
└─────────────────────────────────────┘
核心组件:
# 简化的推荐算法实现
def get_recommendations(user_id, page=1, size=20):
# 获取用户画像
user_profile = get_user_profile(user_id)
# 获取候选集
candidates = []
# 基于标签的推荐
tag_based = get_notes_by_tags(user_profile.tags)
candidates.extend(tag_based)
# 基于协同过滤
similar_users = get_similar_users(user_id)
for similar_user in similar_users:
liked_notes = get_user_liked_notes(similar_user)
candidates.extend(liked_notes)
# 去重和过滤已看过的
candidates = filter_viewed(candidates, user_id)
# 综合排序
scored_candidates = []
for note in candidates:
score = calculate_score(note, user_profile)
scored_candidates.append((note, score))
# 返回TOP N
scored_candidates.sort(key=lambda x: x[1], reverse=True)
return scored_candidates[(page-1)*size:page*size]
2014年12月,小红书上线”福利社”,开始电商业务探索。这带来了全新的技术挑战:
| 业务场景 | 技术挑战 | 解决方案 |
|---|---|---|
| 商品管理 | SKU体系复杂 | 设计灵活的商品模型 |
| 库存管理 | 防止超卖 | Redis原子操作+数据库事务 |
| 订单系统 | 状态机管理 | 订单状态流转引擎 |
| 支付接入 | 支付安全 | 支付宝/微信支付SDK |
| 物流对接 | 多物流商 | 统一物流接口抽象 |
福利社电商系统架构 (2015.06)
┌────────────────────────────────────────────┐
│ 前端展示层 │
│ (商品列表、详情页、购物车、订单) │
└────────────────────────────────────────────┘
│
┌────────────────────────────────────────────┐
│ API网关层 │
│ (路由、认证、限流) │
└────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
↓ ↓ ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│商品服务 │ │订单服务 │ │用户服务 │
└──────────┘ └──────────┘ └──────────┘
│ │ │
↓ ↓ ↓
┌────────────────────────────────────────────┐
│ MySQL分库分表 │
│ 商品库 | 订单库 | 用户库 | 库存库 │
└────────────────────────────────────────────┘
│
┌────────────────────────────────────────────┐
│ Redis缓存层 │
│ (热点商品、库存扣减、购物车) │
└────────────────────────────────────────────┘
防止超卖是电商系统的核心挑战之一:
# 库存扣减的实现(简化版)
def decrease_stock(sku_id, quantity):
# 使用Redis实现库存预扣减
redis_key = f"stock:{sku_id}"
# Lua脚本保证原子性
lua_script = """
local stock = redis.call('get', KEYS[1])
if tonumber(stock) >= tonumber(ARGV[1]) then
redis.call('decrby', KEYS[1], ARGV[1])
return 1
else
return 0
end
"""
result = redis.eval(lua_script, 1, redis_key, quantity)
if result == 1:
# 异步更新数据库
update_db_stock.delay(sku_id, quantity)
return True
else:
return False
技术团队发展:
2013年:3人 (全栈开发)
2014年:15人 (前后端分离)
2015年:50人 (专业化分工)
组织架构演进:
2013: CTO ─── 工程师(3)
2014: CTO ┬── 后端组(8)
├── 前端组(4)
└── 运维组(3)
2015: CTO ┬── 基础架构组(10)
├── 业务开发组(20)
├── 数据组(8)
├── 质量保障组(7)
└── 运维组(5)
| 实践领域 | 具体措施 | 工具/方法 |
|---|---|---|
| 代码管理 | Git工作流 | GitLab + Code Review |
| 持续集成 | 自动化构建 | Jenkins + 单元测试 |
| 部署流程 | 灰度发布 | Fabric + 脚本化部署 |
| 监控告警 | 基础监控 | Zabbix + 自定义脚本 |
| 文档管理 | 技术文档 | Confluence + Markdown |
随着用户量增长,性能问题逐渐凸显:
性能优化时间线:
2014.Q1: 首页加载慢 → 引入CDN + 图片懒加载
2014.Q2: 数据库压力大 → 读写分离 + 缓存优化
2014.Q3: API响应慢 → 接口合并 + 数据预加载
2014.Q4: 高峰期卡顿 → 限流降级 + 队列削峰
2015.Q1: 搜索性能差 → 引入Elasticsearch
2015.Q2: 推荐计算慢 → 离线计算 + 缓存预热
| 问题类型 | 发生时间 | 影响范围 | 解决方案 | 改进措施 |
|---|---|---|---|---|
| 数据库宕机 | 2014.03 | 全站不可用2小时 | 紧急切换从库 | 主从自动切换 |
| 缓存雪崩 | 2014.07 | 部分功能异常 | 重启缓存服务 | 缓存预热机制 |
| 流量突增 | 2014.11 | 响应变慢 | 紧急扩容 | 弹性伸缩方案 |
| 代码Bug | 2015.02 | 推荐异常 | 快速回滚 | 灰度发布流程 |
| DDoS攻击 | 2015.05 | 访问受限 | 启用高防IP | 安全防护升级 |
数据规模增长(2013-2015):
类型 2013年底 2014年底 2015年底
用户数 1万 50万 500万
日活跃 0.3万 15万 100万
笔记数 0.5万 100万 1000万
图片存储 10GB 1TB 50TB
数据库 100MB 10GB 500GB
技术应对措施:
关键技术决策树:
2013.10 ─┬─ 选择Python还是Java?
└─> Python (快速开发) ✓
2014.02 ─┬─ 自建机房还是云服务?
└─> 阿里云 (弹性扩展) ✓
2014.08 ─┬─ 单体应用还是微服务?
└─> 暂时保持单体 (团队规模小) ✓
2015.03 ─┬─ SQL还是NoSQL?
└─> MySQL为主+Redis缓存 (成熟稳定) ✓
2015.09 ─┬─ 自研还是开源?
└─> 优先开源方案 (降低成本) ✓
| 时间 | 事件 | 技术意义 | 业务影响 |
|---|---|---|---|
| 2013.12 | App 1.0上线 | 完成从0到1 | 获得首批种子用户 |
| 2014.03 | 社区功能上线 | UGC系统搭建完成 | 内容生产成本大幅降低 |
| 2014.08 | 用户突破10万 | 架构首次优化 | 验证产品模式 |
| 2014.12 | 福利社上线 | 电商技术体系建立 | 商业模式探索 |
| 2015.03 | 获得B轮融资 | 技术团队扩张 | 加速产品迭代 |
| 2015.06 | 日活突破50万 | 推荐系统初见成效 | 用户增长加速 |
| 2015.11 | 双11大促 | 高并发处理能力验证 | 电商业务突破 |
早期快速发展积累的技术债务:
这个阶段奠定的基础对小红书后续发展产生深远影响:
技术基因形成:
┌─────────────────────────────────┐
│ 快速迭代 + 数据驱动 │
│ 用户体验 + 技术创新 │
│ 开放心态 + 工程文化 │
└─────────────────────────────────┘
↓
影响后续技术决策
↓
┌─────────────────────────────────┐
│ • 微服务化改造的时机选择 │
│ • AI技术的早期投入 │
│ • 全球化架构的前瞻布局 │
└─────────────────────────────────┘
2013-2015年是小红书技术发展的奠基期。这三年里,技术团队从零开始,构建了支撑百万用户的技术体系,完成了从内容工具到社区平台再到电商探索的多次转型。
关键成就:
主要挑战:
这个阶段的经历为小红书后续的爆发式增长奠定了坚实基础,也为技术团队积累了应对各种挑战的经验。下一章我们将看到,小红书如何在2016-2018年应对用户爆发式增长带来的技术挑战,完成从单体应用到微服务架构的关键转型。
第一章完