您的位置:首页 > 数据库 > Redis

新浪微博Redis应用经验--总结自InfoQ

2015-08-04 20:50 609 查看
1. 平台引入微博时踩的坑:
运维工具和流程从零开始做,运维成熟的速度赶不上业务增长的速度:在还没来得及安排性能调优的工作,fd已经达到默认配置的上限了,最后我们只能趁凌晨业务低峰期重启 Redis 集群,以便设置新的 ulimit 参数
 
平台最开始使用的 Redis 版本是 2.0,因为 Redis代码足够简单,从引入到微博起,我们就开始对其进行了定制化开发,从主从复制,到写磁盘限速,再到内存管理,都进行了定制。导致的结果是,有一段时间,微博的线上存在超过5种不同的Redis 修改版,对于运维,bugfix,升级都带来了巨大的麻烦。后来由田风军 @果爸果爸 为内部 Redis 版本提供了不停机升级功能后,才慢慢好转。
 
平台有一个业务曾经使用了非默认 db ,后来费了好大力气去做迁移
 
平台还有一个业务需要定期对数据进行 flush db,以腾出空间存储最新数据。为了避免在 flush db 阶段影响线上业务,我们从 client 到 server 都做了大量的修改。
 
平台每年长假前都会做一些线上业务排查,和故障模拟(2013年甚至做了一个名叫Touchstone 的容灾压测系统)。2011年十一假前,我们用 iptables 将 Redis 端口的所有包都 drop 掉,结果 client 端等了120 秒才返回。于是我们在放假前熬夜加班给 client 添加超时检测功能,但真正上线还是等到了假期回来后。
 
2. 遇到的麻烦:
第一个碰到的麻烦是 Redis 的 hgetAll 在 hashsize 较大的场景下慢请求比例较高。我们调整了 hash-max-zip-size,节约了1/3的内存,但对业务整体性能的提升有限。最后,我们不得不在Redis 前面又挡了一层 memcache,用来抗 hgetAll 读的问题。
 
第二个麻烦是新上的需求:“我关注的人里谁关注了他”,由于用户的粉丝列表可能不全,在这种情况下就不能用关注列表与粉丝列表求交集的方式来计算结果,只能降级到需求的字面描述步骤:取我的关注人列表,然后逐个判断这些人里谁关注了他。client端分批并行发起请求,还好 Redis 的单个关系判断非常快。
第三个麻烦,也是最大的麻烦,就是容量增长的问题了。最初的设计方案,按uid hash 成 16 个端口,每台 64G 内存的机器上部署 2 个端口,每个业务 IDC机房部署一套。后来,每台机器上就只部署一个端口了。再后来,128G 内存的机器还没有进入公司采购目录,64G 内存就即将 OOM了,所以我们不得不做了一次端口扩容:16端口拆64端口,依然是每台 64G
内存机器上部署 2 个端口。再后来,又只部署一个端口。再后来,升级到 128G内存机器。再后来,128G 机器上出现 OOM 了!现在怎么办?
 
3. 新浪微博容量解决方案
为了从根本上解决容量的问题,我们开始寻找一种本质的解决方案。最初选择引入Redis 作为一个 storage,是因为用户关系判断功能请求的数据热点不是很集中,长尾效果明显,cache miss可能会影响核心接口性能,而保证一个可接受的 cache 命中率,耗费的内存与 storage 差别不大。但微博经过了 3年的演化,最初作为选择依据的那些假设前提,数据指标都已经发生了变化:随着用户基数的增大,冷用户的绝对数量也在增大;Redis
作为存储,为了数据可靠性必须开启rdb 和 aof,而这会导致业务只能使用一半的机器内存;Redis hash 存储效率太低,特别是与内部极度优化过的 RedisCounter对比。种种因素加在一起,最终确定下来的方向就是:将 Redis 在这里的 storage 角色降低为 cache 角色。
 
前面提到的微博关系服务当前的业务场景,可以归纳为两类:一类是取列表,一类是判断元素在集合中是否存在,而且是批量的。即使是Redis 作为 storage 的时代,取列表都要依赖前面的 memcache 帮忙抗,那么作为 cache 方案,取列表就全部由 memcache代劳了。批量判断元素在集合中是否存在,redis hash 依然是最佳的数据结构,但存在两个问题:cache
miss 的时候,从 db 中获取数据后,setcache 性能太差:对于那些关注了 3000 人的微博会员们,set cache 偶尔耗时可达到 10ms 左右,这对于单线程的 Redis来说是致命的,意味着这 10ms 内,这个端口无法提供任何其它的服务。另一个问题是 Redis hash 的内存使用效率太低,对于目标的 cache命中率来说,需要的 cache 容量还是太大。于是,我们又祭出 “Redis定制化”的法宝:将 redis hash替换成一个“固定长度开放hash寻址数组”,在 Redis
看来就是一个 byte 数组,set cache 只需要一次 redis set。通过精心选择的hash 算法及数组填充率,能做到批量判断元素是否存在的性能与原生的 redis hash 相当。
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Redis 微博 架构