第1页
知乎架构变迁史
李申申
第2页
李申申是谁
第8页
RU 11M+ MAU 80M+ MPV 220M+
第9页
2010.10
第11页
You jump off a cliff and you assemble an
aeroplane on the way down.
Reid Hoffman
第12页
Linode 512M
第15页
你永远不知道明早醒来会面对什么问题
第16页
宕机@知乎
第18页
Picture Upload Picture Storage
LVS Nginx Web
M MySQL
LVS Nginx Web
S MySQL
Mailgun
Mail
M Redis
S Redis
第19页
MySQL 经典问题
主从延迟
第20页
资源隔离
第21页
内网优化
第22页
硬盘升级
第23页
应用层灵活调用
第24页
Redis Shard
第25页
node3 计算 hash
Key
计算 hash
0/232
node1
计算 hash
Key
计算 hash
计算 hash node4
计算 hash node2
第26页
github.com/zhihu/redis-shard
第27页
工具是一个过程 用大小形状都合适的物体,以最有效的方式完成工作
第28页
Profiling
第29页
Werkzeug
第30页
Puppet
第31页
Shipit
第32页
知乎邀请制
第34页
申请注册
第36页
日志系统
第37页
分布式收集 集中存储 可订阅
实时 简单
第38页
Scribe Kafka Flume
无法订阅
Scala Java
第39页
Kids
Kids is Data Stream
第40页
App App
Publish
Publish
Agent
App
Publish
Agent
Agent
Agent
Subscribe
Kids Server
Log Analyzer
Psubscribe
Subscribe
Log Analyzer
Log Analyzer
第41页
MultipleStore
⑥ Notify Storer
Storer Thread
Fetch Global Message Queue
Store
BufferStore PriorityStore
Worker Thread
Client Client
④ Push ③ Publish
Message Latest
Message Latest
Message Latest
⑦ Fetch
Worker Thread
Client
⑤ Notify Worker
② Accept
Master Thread
① Connect
Accept
Connect
Subscribe⑧/PMsuebssscargibee
Client
App (Publisher)
App (Subscriber)
第43页
github.com/zhihu/kids
第44页
添加回答
更新通知
更新动态
更新搜索索引 ?
失效缓存
判断是否 Spam
更新回答计数
判断内容质量
更新个人主页
?
是否非法
内容审核
??
?
第45页
Event Driven Architecture
第46页
Miller Master
Miller Worker
Worker 01 Worker 02
Worker N
Sink Beanstalkd
第47页
① ②
MySQL
Web
④ ③
Sink
④④
noti-miller Master
⑤
search-miller Master
⑤
Beanstalkd
⑥
⑥
noti-miller Worker
⑦
noti server
search-miller Worker
⑦
indexer
第48页
In 100+ Out 1500+
第49页
Miller Master
Miller Worker Worker 01 Worker 02
Worker N
Sink Beanstalkd
LVS Nginx Web
M MySQL
LVS Nginx Web
S MySQL
M Redis
S Redis
第50页
页面渲染优化
第52页
HomeUI
FeedUI
SidebarUI
Item1UI
Item2UI
NavigatorUI
Data
QuestionUI
AnswerUI
第53页
HomeNode
FeedNode
SidebarNode
Data
Item1Node
Item2Node
NavigatorNode
QuestionNode AnswerNode
第54页
ZhihuNode
第55页
class AnswerVoteBarV2(ZhihuNode):
! def init(self, answer_id): self.answer_id = answer_id
! def template_v2(self): return "v2_uimodule_answer_votebar.html"
! def prime(self): models.AnswerDAO.prime_get_vote(self.login_id, self.answer_id)
def obj(self): vote = models.AnswerDOA.get_vote(self.login_id, self.answer_id) return ObjectDict(vote=vote)
第56页
Question 500ms -> 150ms Feed 1s -> 600ms
第57页
Service-oriented architecture
第58页
RPC 框架变迁史
第59页
Wish
Protocol Buffers STP TCP
第60页
Snow
JSON STP TCP
第61页
Zone
第62页
Protocol Versioning
Apache Avro IDL API Protocol
Protocol Generator
Sync Client Async Client
Connection Pool
Communication
&
Transport Protocols
Async Server
第63页
Apache Avro - IDL
// Google Protocol Buffer
// Apache Avro
message CalcResponse {
protocol Calc {
enum Result {
error ZeroDivision {
OK = 0;
string message;
ZERO_DIVISION = 1;
}
}
required Result result = 1;
int divide(int a, int b) throws ZeroDivision;
optional int32 c = 2;
}
}
message CalcRequest {
int32 a = 1;
int32 b = 2;
}
service Calc {
rpc Divide (CalcRequest) returns (CalcResponse);
}
第64页
Apache Avro - API Protocol File
// Wish’s generated files… xxx_pb2.py xxx_stub.py descriptor_pb2.py
// Apache Avro’s generated file, simply a snippet of JSON {
"Calc": { "messages": { "divide": { "errors": ["ZeroDivision"], "reqest": [{"name": "a", "type": "int"}, {"name": "b", "type": "int"}], "response": "int"}}, "namespace": None, "protocol": "Calc", "types": [ {"fields": [{"name": "message", "type": "string"}], "name": "ZeroDivision", "type": "error"} ]
} }
第65页
Server Example
import snow class Calc(snow.APIBase):
def divide(self, a, b): if b == 0:
return {"code": 1, "msg": "Zero division."}
return {"code": 0, "c": a / b}
!
snow.Server(Calc(), port=9000).run()
import zone from proto import protos
!
class Calc(zone.ZoneAPI):
! def divide(self, a, b): if b == 0: raise zone.ZoneCustomException(name="ZeroDivision")
return a / b
!
zone.Server([Calc(protos["Calc"])], port=9000).run()
第66页
Header
Body
Serializer (Avro / JSON)
Transporter (Binary/STP)
TCP
第67页
Consul
第68页
Tracing
第69页
知乎业务服务结构图
聚 合 话题 Feed 层
⾸首⻚页 Feed
发现
搜索
推荐
收藏
圆桌
内
容 问答
专栏
通知
私信
已读
层
基 础 ⽤用户 层
评论
图⽚片
推送
分享
话题
邮件
短址
数据服务
逻辑服务
通道服务
第70页
Miller Beantalk
LVS01
keepAlived
LVS02
Nginx01
Nginx02
Web01
Web02
WebN
Haproxy01
keepAlived
Haproxy02
Feed Service
Member Service
···
前端展⽰示层 后端业务逻辑层
Sink
Kids
MySQL
Redis
Cassandra
存储&通信层
第71页
知乎专栏的全新实践
第72页
传统网站的开发模式
前后端代码交叉 工程师互相等待 前端代码部署成本高
第73页
Web App RESTful API Server
RPC Server
MySQL
Redis
Workers
第74页
前后端分离,逻辑更清晰 AngularJS:代码复用、快速开发
并行开发 独立部署
第75页
<(▰˘◡˘▰)>
产品设计师也能修改代码了
第76页
工具要不断跟上
第77页
Dash
第78页
Heroin
第79页
Radius
第80页
CFB
第81页
Crony
第82页
Oops
第83页
Boxen
第84页
想各种办法发挥自我创新 其实就是找各种办法刺激工程师们
第85页
Hackathon
第87页
Tink Day
第91页
谢谢