我using redis to store bits to track hourly, daily, weekly, and monthly active users。每当我有一个具有唯一user
,hour
或eventType
的事件时,就会存储一位。
我正在使用的redis命令(节点客户端)是 client.setbit(key, id, 1);
其中key
类似login-mobile-2015-11-14-04
而id
是六位整数(指用户)。
在短短几天内,我达到了heroku redis免费计划的25MB限制,但最大实际数据量(基于独特事件和用户的数量每天192000
,这是waaay比25MB更少的字节。我怀疑我的密钥有点太长或有什么问题,但我真的不太了解redis,所以我想问一下。
答案 0 :(得分:2)
答案在Redis字符串内部数据结构中。 Redus使用SDS字符串,有时它真正重要的是解决它的工作原理。最重要的是SDS中的内存分配策略。
实际上,当它小于SDS_MAX_PREALLOC(1MB)时,它只是将原始大小加倍。当内存不足时,这类似于C ++向量分配策略。这就是字符串追加操作不需要每次都分配内存的原因。
为什么这对你来说很重要。 SETBIT只使用字符串作为容器,因此使用六位整数作为userId(在最坏的情况下)999,999 / 8 = 125,000字节+ 8字节开销。但根据分配策略,每个密钥可能会有高达250,000 + 8字节的开销。
所以有些数学:
因此,在最坏的情况下,您只需在4天内花费25 MB。但是在最好的情况下,那么125 kb是最大密钥存储器,你在7-8天内花费25 mb。
BITSET既快又好但消耗大量内存。如果您有大量在线用户,则使用BITSET获取每日,每周和每月数据看起来是正确的决定。 Bitset不是解析数据的最佳选择。
分析您的每小时数据 - 可能正在使用SET允许使用更少的内存 - 您的userId是整数(4个字节),因此128kb是每小时~32,000个用户。另外看看 redis memory optimization guide - 你可能会发现很多关于redis中实际内存使用的有趣内容。
关于SET解决方法 - 您的每小时在线时间少于~32,000个用户 - SET是您的选择。
您也可以使用redis命令DEBUG SDSLEN <key name>
调试BITSET键 - 它显示为bitset数据下的SDS字符串分配的内存。