BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

Redis计数在新浪微博的应用

| 作者 田风军 关注 0 他的粉丝 发布于 2014年3月19日. 估计阅读时间: 6 分钟 | GMTC大前端的下一站,PWA、Web框架、Node等最新最热的大前端话题邀你一起共同探讨。

 微博业务的迅速发展,对基础架构层面的要求也越来越高。新浪作为国内最早使用redis,并且是国内最大的redis使用者,在redis的使用上,也在逐步优化和提高。

作为微博中一项重要的数据,计数类业务在微博业务中占的比重和重要性逐步提高。计数结果的准确度直接影响用户体验,并且很容易引起用户的投诉。在计数业务上,在不断的优化和改进中,我们主要经历了以下三个阶段:

初级阶段

从2010年开始,使用redis-2.0版本。在最初业务数据比较少的时候,表现相当不错。但随着数据量和请求量的不断增加,一些问题逐渐暴露出来。

  • 主从同步问题

    首先遇到的是主从的同步问题。它的原理是当master接收到slave的同步请求后,把内存的数据fork出一个子进程dump出来,形成rdb文件,然后传到slave,slave再把这个文件加载到内存,之后的增量更新由master在执行完每条修改命令后立即同步给slave。 在网络出现问题时,比如瞬断,会导致slave里的数据全部重传。对单个端口来说,如果数据量小,那么这个影响不大,而如果数据量比较大的话,就会导致网络流量暴增,同时slave在加载rdb时无法响应任何请求。

  • 持久化问题

    计数业务中多数使用redis作为存储,因此都开启了aof,并配置为每秒做一次fsync操作将写操作刷新到磁盘。随着aof的增长,需要定期rewrite。Rewrite的机制和生成rdb的过程类似,都是fork出一个子进程来完成的,子进程对于磁盘的持续写入会导致父进程的fsync操作阻塞,造成大量请求超时。

  • 版本升级问题

    由于redis在使用初期bug较多,版本迭代频繁,而版本升级需要关闭redis进程并重新加载aof。对于大量使用redis的微博业务来讲,这样的升级成本也越来越难以承受。

  • 内存使用问题

    2.0版本的redis,在内存使用上相对比较粗放,对于计数这样一个简单的key-value,占用的内存达到100字节以上,存在比较多的优化空间。

进阶阶段

针对redis使用初期存在的问题,我们逐个进行了改进。主从复制参考mysql的同步方式,使用rdb+aof结合的方式,解决了网络瞬断引起的重传问题,同时限制子进程做后台dump时对磁盘的写入,期间暂停主进程的fsync操作,解决了慢请求的问题。

针对计数业务,我们开发了专用的版本redisscounter,单个key-value占用的内存key的长度加4个字节的value,将内存的使用量降低到原来的1/4以下。通过预先分配内存数组和double hash技术,消除了redis中hash表的大量指针开销。

对于版本升级的问题,我们将redis的核心处理逻辑封装到动态库,内存中的数据保存在全局变量里,通过外部程序来调用动态库里的相应函数来读写数据。版本升级时只需要替换成新的动态库文件即可,无须重新载入数据。通过这样的方式,版本升级只需执行一条指令,即可在毫秒级别完成代码的升级,同时对客户端请求无任何影响。

有了上面的改进后,新版本开始大量应用,多数业务都可以作为完整的存储替代以前的mysql+memcached组合。对于微博的评论数和转发数,由于微博条目不断增加,无法保存全量数据,因此采用mysql+redisscounter组合的方式,mysql保存全量数据,使用两组redisscounter保存最近几个月的热数据,通过定期滚动两组redisscounter里的数据来清理冷数据。

高级阶段

随着微博的发展,针对单条微博的计数也不断增加,从原来的评论数、转发数,又增加了表态数,2013年还上线了阅读数。Redisscounter不能很好的解决这类扩展问题,同时上面的mysql+redisscounter的滚动方式也过于复杂,定期的滚动操作很容易出现问题。针对这类问题,我们再度做出改进,将key由原先的字符串改成微博id,同时对于每条微博的评论转发等计数,我们统计发现,绝大多数微博的计数都可以用10~15个bit来保存,因此可以将多个计数保存到一个4字节的value里,过大的计数值在内存中另外开辟一块空间来保存。这样通过一条get命令即可获取该微博的所有计数。同时针对微博业务的特点,越老的微博被访问的次数就会越少,在内存使用多个数组保存不同范围的微博,内存不足时将最老的一组微博dump到ssd上,内部自动实现的滚动可以保证热微博全部在内存里。对于落到ssd上的老数据的访问,通过异步的io线程来读写,经过这样的改进后,去掉了原先的mysql存储,降低了业务开发成本和运维成本。

从redis在计数业务上的发展经历可以看出,技术的进步是由业务的需求推动的。随着业务的发展,还会遇到更多新的挑战。希望我们走过的这些改进之路对于读者在使用redis的过程中能有所帮助。

感谢张龙对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

新浪微博的性能真心跟屎一样…… by Shan Yang

如题

哈哈 by jiang changren

楼上的太直白了

喜感 by jianfei zhu

不用微博

查看个人信息时性能不好 by li rongzun

微博在获取个人信息是性能很差,鼠标放到头像上半天转不出来

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

4 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT