Redis中sorted set调优

背景

公司的监控系统的缓存是使用的redis中的sorted set的数据结构来存储。但是使用过程中发现redis的内存消耗特别多,甚至撑暴内存,导致引发线上问题。后来经过计算,发现redis实际消耗的内存远比理论应消耗的内存大(理论上一个数据点包含一个时间戳32位,一个数据值最多64位,总共12字节,而实际占用空间达到150字节左右,相差10倍),这就引发了我们对sorted set的深入研究

如何使用

我们使用sorted set存储监控数据的格式为

  • key: metric_id (指标id,如cpu,内存)
  • score: unix时间戳
  • member: unix时间戳|监控数值(如1432343233|60)

获取监控数据的时候使用 ZRANGE metric_id 0 1432343233 就可以得到按时间排序的各个数据点的值

为何占用大量空间

sorted set的存储设计是这样的,在一个key下如果score的个数小于等于128时,采用一个最紧凑的数组来存储,不会占用额外的空间。而当个数大于128时,会使用额外的数据结构一个ziplist用于快速查找对应,一个跳表来排序,这两个数据结构会产生大量空间占用。具体可以参考http://origin.redisbook.com/datatype/sorted_set.html#sorted-set-chapter

如何优化

由于我们使用对监控数据的存储是分不同的粒度来存储的,单个粒度的数据redis中保存的数据最多不超过400个,于是可以选择将redis默认的zset-max-ziplist-entries=128的设置修改为400,即可以达到所有数据都用最简单的数组来存储,节省了大量空间。当然这样子会在效率上产生一定的影响,不过由于我们对数据的插入操作,只会在数组尾部进行,因此不会需要移动内存,而数据清理只会在数组头部进行,也只需要一次memmove即可,所以评估下来造成的效率影响应该可以接受。

comments powered by Disqus