关系链的特点之读扩散和写扩散

微博后台架构浅析——读扩散pull、写扩散push、混合模式(push+pull)——相关cache(redis,memcache)

之前在网上看到关于Twitter、Sina以及腾讯微薄的一些实现技术,这个简单做个摘要。

1、读扩散还是写扩散?

inbox: 收件箱,你收到的消息,即你所关注的人发布的消息。

outbox: 发件箱,你发布的消息。

写扩散(Push)

该方式为每个用户维护一个订阅列表,记录该用户订阅的消息索引(一般为消息ID、类型、发表时间等一些元数据)。每当用户发布消息时,都会去更新其follower的订阅列表。

优点:读很轻。初始化时仅需要读取自己的inbox即可。

缺点:写很重。每发布一个消息,会导致大量的写操作。

注:一般来说,用户发布消息,并不会更新所有followers的订阅列表,仅更新在线followers即可。

读扩散(Pull)

该方式为每个用户维护一个发送列表,记录该用户所有发表过的消息索引。

优点:写很轻,节省空间。用户每发布一条消息,仅需更新自己的outbox。

缺点:读操作很重,计算量大。假设你收听了1k用户,则初始化时,需要从1k个用户的outbox拉取消息,然后计算获得最新的n条消息。

混合模式(Push+Pull)

该方式既为读写扩散的结合,根据用户followers的数量来决定是读扩散还是写扩散。例如followers大于1k的,则使用读扩散,否则使用写扩散。

从目前现在网上的一些资料来看,Twitter是写扩散,腾讯微薄是读扩散,新浪微薄则是二者结合。

2、关于Cache

对于一个千万级甚至亿级用户的大型网站来说,合理使用Cache至关重要。

一个用户的核心数据由如下几个部分组成:inbox,outbox,关系链,消息内容。

  • inbox:主要缓存消息索引,仅为在线用户缓存,从Timyang的PPT来看,新浪微薄估计是使用redis的list或set实现。
  • outbox:缓存一定数量(例如200)条最近发表的消息。
  • 关系链:following相对于followers来说,缓存容易些,follower加载开销比较大,例如刘翔在腾讯微薄的听众超过1600万。
  • 消息内容:按内容年龄缓存;一般需要多份支持容灾;需要缓存xml,json,rss,atom等多种格式的缓存以供API使用。

以Twitter为例,其将Cache分为四类:Vector Cache,Row Cache,Page Cache,Fragment Cache,均使用memcached实现。其中:

  • Vector Cache主要缓存用户的inbox以及outbox索引,其命中率高达99%;
  • Row Cache主要缓存用户关系链数据,以及Tweets内容,命中率为95%;
  • Fragment Cache缓存Tweet的xml,json,rss,atom四种格式数据,以供API使用,命中率为95%;
  • Page Cache主要原来缓存那些高人气用户的个人主页,命中率仅为40%。

下图为TwitterCache架构图:

Twitter为啥要为API通道设置Fragment Cache和Page Cahce呢?其原因是Twitter的80%流量来自API。

下面以新浪微薄介绍一下Cache流程:

消息发布流程:

  1. 更新自己的outbox
  2. 加载followers列表
  3. 更新followers inbox

获取首页流程:

  1. 检查inbox cache是否可用
  2. 获取关注列表
  3. 聚合内容,获得消息索引
  4. 根据索引,返回最终聚合的消息内容

3、关于存储

目前Twitter和新浪的落地存储,都是使用MySQL。而腾讯微薄则使用采用SSD+大文件存储(每次写操作都是append操作,写操作可以先用内存缓存,达到适当大小合并,尽量减少随机写)。其他细节因不清楚或不方便透露,不做细述。

4、关于洪峰处理。

一般用异步队列处理方式。消息队列产品有:Kestrel(twitter使用Scala实现),RabbitMQ(使用Erlang实现),MemcacheQ。

Twitter 09年时,用户的平均followers数量为126个。按照每秒400消息发布数算,那每秒就需要推送126*400=50400条消息出去。为了削 峰,Twitter自己用Scala实现了一个分布式消息队列Kestrel,其代码仅为1200行,运行在3台机器上,其使用memcached协议, 其Server之间无共享状态,且全内存。新浪使用的是MemcacheQ。

原文地址:http://blog.163.com/[email protected]/blog/static/1322296552013430114959121/

时间: 2024-10-05 04:27:49

关系链的特点之读扩散和写扩散的相关文章

what is feeding and what is 读扩散 and 写扩散?

what is feeding? 通俗点说feed系统就是当你登陆进对应网站后:微信朋友圈的动态.人人网上看到的一件件新鲜事.新浪微博上推到你面前的一条条新围脖等等.系统中的每一条消息就是一个feed.feed的获取方式主要有两种:push(推)以及pull(拉).也就是接下来所说的读扩散和写扩散. feed流业务最大的特点是"我们的主页由别人发布的feed组成",获得朋友圈消息feed流集合,从技术上说,主要有"拉取"与"推送"两种方式.fee

1.30 Java周末总结①控制显示多少位小数位②读txt和写txt模拟ATM数据库

1.30 Java周末总结①控制显示多少位小数位②读txt和写txt模拟ATM数据库 一.控制显示多少位小数位 有些时候小数位数太多了,想保留多少位小数,这里介绍一种利用四舍五入保留想要的小数位数Math.round四舍五入到整数位,所以把小数乘以整10或整百,在除以整10或整百,就得到想要的位数了 double a = 3.14159265359;double weishu = 5;double b = Math.pow(10,weishu);a = Math.round(a*b)/b; 二.

Linux中文件的可读,可写,可执行权限的解读以及chmod,chown,chgrp命令的用法

一.文件权限解读 如上图所示,开头的-rwxrw-r--这一字符串标识文件权限. 这个字符串有10位,可以分为4段来解读.注:r--可读,w--可写,x--可执行. 第一段(第1位)表示是目录还是文件,-表示是文件,d表示是目录: 第二段(第2-4位,共3个字符串)表示文件所属用户对它的权限: 第三段(第5-7位,共3个字符串)表示文件所属用户组用户对它的权限: 第四段(第8-10位,共3个字符串)表示其他用户对它的权限: 注:我们用3位8进制来表示文件的权限,r用4标识,w用2标识,x用1标识

C#多线程:使用ReaderWriterLock类实现多用户读/单用户写同步

C#多线程:使用ReaderWriterLock类实现多用户读/单用户写同步 - mile - 博客园http://www.cnblogs.com/lhws/archive/2014/03/31/3636757.html 摘要:C#提供了System.Threading.ReaderWriterLock类以适应多用户读/单用户写的场景.该类可实现以下功能:如果资源未被写操作锁定,那么任何线程都可对该资源进行读操作锁定,并且对读操作锁数量没有限制,即多个线程可同时对该资源进行读操作锁定,以读取数据

修改Oracle GoldenGate(ogg)各个进程的读检查点和写检查点

请注意:请慎重修改Oracle GoldenGate(ogg)各个进程的读检查点和写检查点.请确保已经 掌握 ogg 各个进程的读检查点和写检查点的具体含义. BEGIN {NOW | yyyy-mm-dd[:hh:mi:[ss[.cccccc]]] | EOF | SEQNO <sequence number>} --修改抽取进程的开始抽取点:(即:myext的读检查点) alter extract myext BEGIN yyyy-mm-dd:hh:mi:ss alter extract 

使用ReaderWriterLock类实现多用户读/单用户写同步

使用ReaderWriterLock类实现多用户读/单用户写同步[1] 2015-03-12 应用程序在访问资源时是进行读操作,写操作相对较少.为解决这一问题,C#提供了System.Threading.ReaderWriterLock类以适应多用户读/单用户写的场景. 该类可实现以下功能:如果资源未被写操作锁定,那么任何线程都可对该资源进行读操作锁定,并且对读操作锁数量没有限制,即多个线程可同时对该资源进行读操作锁定,以读取数据.如果资源未被添加任何读或写操作锁,那么一个且仅有一个线程可对该资

【转】Linux中文件的可读,可写,可执行权限的解读以及chmod,chown,chgrp命令的用法

chmod是更改文件的权限 chown是改改文件的属主与属组 chgrp只是更改文件的属组. 一.文件权限解读 如上图所示,开头的-rwxrw-r--这一字符串标识文件权限. 这个字符串有10位,可以分为4段来解读.注:r--可读,w--可写,x--可执行. 第一段(第1位)表示是目录还是文件,-表示是文件,d表示是目录: 第二段(第2-4位,共3个字符串)表示文件所属用户对它的权限: 第三段(第5-7位,共3个字符串)表示文件所属用户组用户对它的权限: 第四段(第8-10位,共3个字符串)表示

小技巧-读优与写优

读优与写优 读优与写优是面对输入或者输出数据规模比较巨大的时候,cin和cout会TLE,即使是scanf和printf也会浪费大量时间,这时我们就可以使用读优与写优 一个小小的冷知识 cin和cout之所以慢,是因为它有很多的保险设置,浪费了时间,所以只要加入这段代码 1 std::ios::sync_with_stdio(false); 这样就可以取消cin和cout的保险装置 正经的读优与写优 原理 用cin和cout或者scanf和printf读写单个数字时,速度会比getchar和pu

java创建文本、文件、读文件、写文件

1 package Head18; 2 3 import java.io.BufferedReader; 4 import java.io.File; 5 import java.io.FileNotFoundException; 6 import java.io.FileReader; 7 import java.io.FileWriter; 8 import java.io.IOException; 9 10 public class Mkdirs_FileRW { 11 public st