架构设计摘录

写扩散和读扩散

今天看一篇文章时,提到了微信的群聊是写扩散的,第一次接触到写扩散这个名词,于是去查了下资料,有写扩散就有读扩散嘛

定义如下:

根据上面的定义,我是这样理解的,什么是写扩散,什么是读扩散,要怎么区分他们,区别之处就在于“主动”

写扩散是主动把消息写到订阅者的消息列表里,这样订阅者就不用去我的outbox拉取消息 ,所以当我要是有很多订阅者时,我就要写很多次,这就是上面定义中说的写很重

读扩散是主动去拉取被订阅者的outbox,这样就不需要被订阅者主动写消息到我的消息列表里来,所以当我要是订阅了很多人时,我就要去读取这些人的所有新消息,所以就出现了读很重

Clustering VS Sharding

引用:Pinterest架构解析 - 知乎

下面着重讲解一下Pinterest在数据库层是如何扩容的。面对集群和分片两种方法,Pinterest的工程团队选择了更加简洁的分片模式。

  • 集群和分片的特点

集群模式(Cassandra, HBase等等)的一个好处就是没有SPOF(Single Point of Failure),这可以保证服务的高可用,而且,数据在节点上的分布、迁移都是自动完成的,对用户透明。从技术审美的角度来看,集群是非常“优雅”的解决方案。但是,集群中的各个节点之间互相通信,需要复杂的协议来维持数据在各节点的一致性,这种复杂度带来的是各种失败模式(Failure Modes),特别是当这种技术还不成熟、没有经过广泛验证的时候,故障是难以预料的。正因为各个节点之间互相通信,当一个bug出现的时候,影响的不仅仅是自身节点,会扩散到集群的所有节点。用Pinterest工程师的话来说就是:“发生了数据丢失,但是我们不知道哪一部分丢失了,这比丢失所有数据还要糟糕。” 需要升级的时候,发生故障的可能性更高,因为需要考虑不同版本的节点之间的兼容性问题。

分片模式需要应用层手动完成数据分布。各个分片的节点之间没有通信,这能保证故障能被隔离在一个节点内部。在这种架构中需要一个master节点来对请求做分发,这是一个SPOF,但是和集群算法相比,分发的逻辑相当简单,往往只需要几十行代码,出现程序错误的几率很小。分片的另一个问题是,不支持跨节点的JOIN,也无法保证事务的原子性。如果需要这些功能,都需要在应用层来完成。Pinterest的不同用户之间的数据关联度很低,所以按照用户ID对所有数据分片,并不会给应用层增加太多复杂性。因此,针对Pinterest这个应用的业务特点,数据分片是非常英明的抉择。

  • 分片(Sharding)的实现

Pinterest在每个数据库节点上配置了多个DB,每个DB是一个虚拟分片。通过维护一张分片配置表,就可以查找一个分片ID所在的节点:

  [{“range”: (0,511), “master”: “MySQL001A”, “slave”: “MySQL001B”},
  {“range”: (512, 1023), “master”: “MySQL002A”,  “slave”: “MySQL002B”},
  ...
  {“range”: (3584, 4095), “master”: “MySQL008A”, “slave”: “MySQL008B”}]

Pinterest使用了一个64位全局资源ID来完成数据的定位:

ID = (shard ID << 46) | (type ID << 36) | (local ID<<0)

其中16位用于分片ID,10位用于类型(Pin/board等), 32位用于local ID,也就是数据库中的主键。

举个例子,Pinterest中一个图钉的地址是:

http://www.pinterest.com/pin/241294492511762325/

我们可以分解一下这个全局ID:241294492511762325

Shard ID = (241294492511762325 >> 46) & 0xFFFF = 3429
Type ID  = (241294492511762325 >> 36) & 0x3FF = 1
Local ID = (241294492511762325 >>  0) & 0xFFFFFFFFF = 7075733

所以这个图钉在分片3429上,而且他在数据库Pin表中的ID是7075733。假设这个分片在节点MySQL012A上,我们可以这样访问其数据:

conn = MySQLdb.connect(host=”MySQL012A”)
conn.execute(“SELECT data FROM db03429.pins where local_id=7075733”)

Pinterest是根据用户的ID做数据分片的,也就是说一个用户的数据大部分情况下是在同一个库中。这样做的好处是,在渲染一个用户页面的时候,所有数据可以在同一个库中查询到,大大减少了查询延迟。用户数据会永久存储在一个固定的分片上不会迁移,新增用户会被分配到新的分片ID上。Pinterest预留了4096个分片,可能会随着业务的增长扩展到8192个。

唯一的特例是User表,它是存在一个独立数据库中不分片的。这是为了保证用户注册时用户名/邮箱的全局唯一性约束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

anssummer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值