原文:Fast, easy, realtime metrics using Redis bitmaps
(http://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps/)
getspool.com的重要统计数据是实时计算的。Redis的bitmap让我们可以实时的进行类似的统计,并且极其节省空间。在模拟1亿2千8百万用户的模拟环境下,在一台MacBookPro上,典型的统计如“日用户数”(dailyunique users) 的时间消耗小于50ms, 占用16MB内存。Spool现在还没有1亿2千8百万用户,但是我们的方案可以应对这样的规模。我们想分享这是如何做到的,也许能帮到其它创业公司。
Bitmap以及Redis Bitmaps快速入门(Crash Course on Bitmap and Redis Bitmaps)
Bitmap(即Bitset)
Bitmap是一串连续的2进制数字(0或1),每一位所在的位置为偏移(offset),在bitmap上可执行AND,OR,XOR以及其它位操作。
位图计数(Population Count)
位图计数统计的是bitmap中值为1的位的个数。位图计数的效率很高,例如,一个bitmap包含10亿个位,90%的位都置为1,在一台MacBook Pro上对其做位图计数需要21.1ms。SSE4甚至有对整形(integer)做位图计数的硬件指令。
Redis Bitmaps
Redis允许使用二进制数据的Key(binary keys) 和二进制数据的Value(binary values)。Bitmap就是二进制数据的value。Redis的 setbit(key, offset, value)操作对指定的key的value的指定偏移(offset)的位置1或0,时间复杂度是O(1)。
一个简单的例子:日活跃用户
为了统计今日登录的用户数,我们建立了一个bitmap,每一位标识一个用户ID。当某个用户访问我们的网页或执行了某个操作,就在bitmap中把标识此用户的位置为1。在Redis中获取此bitmap的key值是通过用户执行操作的类型和时间戳获得的。
这个简单的例子中,每次用户登录时会执行一次redis.setbit(daily_active_users, user_id, 1)。将bitmap中对应位置的位置为1,时间复杂度是O(1)。统计bitmap结果显示有今天有9个用户登录。Bitmap的key是daily_active_users,它的值是1011110100100101。
因为日活跃用户每天都变化,所以需要每天创建一个新的bitmap。我们简单地把日期添加到key后面,实现了这个功能。例如,要统计某一天有多少个用户至少听了一个音乐app中的一首歌曲,可以把这个bitmap的redis key设计为play:yyyy-mm-dd-hh。当用户听了一首歌曲,我们只是简单地在bitmap中把标识这个用户的位置为1,时间复杂度是O(1)。
- Redis.setbit(play:yyyy-mm-dd, user_id, 1)
今天听过歌曲的用户就是key是play:yyyy-mm-dd的bitmap的位图计数。如果要按周或月统计,只要对这周或这个月的所有bitmap求并集,得出新的bitmap,在对它做位图计数。
利用这些bitmap做其它复杂的统计也非常容易。例如,统计11月听过歌曲的高级用户(premium user):
(play:2011-11-01∪ play:2011-11-02∪ … ∪ play:2011-11-30)∩premium:2011-11
1亿2千8百万用户的性能比较(Performance comparison using 128 million users)
下面的表格显示了在1亿2千8百万用户上完成的时间粒度为1天,一周,一个月的用户统计的时间消耗比较。
Period | Time(ms) |
Daily | 50.2 |
Weekly | 392.0 |
Monthly | 1624.8 |
优化(Optimizations)
前面的例子中,我们把日统计,周统计,月统计缓存到Redis,以加快统计速度。
这是一种非常灵活的方法。这样进行缓存的额外红利是可以进行更多的统计,如每周活跃的手机用户—求手机用户的bitmap与周活跃用户的交集。或者,如果要统计过去n天的活跃用户数,缓存的日活跃用户使这样的统计变得简单——从cache中获取过去n-1天的日活跃用户bitmap和今天的bitmap,对它们做并集(Union),时间消耗是50ms。
示例代码(SampleCode)
下面的Java代码用来统计某个用户操作在某天的活跃用户。
- import redis.clients.jedis.Jedis;
- import java.util.BitSet;
- ...
- Jedis redis = new Jedis("localhost");
- ...
- public int uniqueCount(String action, String date) {
- String key = action + ":" + date;
- BitSet users = BitSet.valueOf(redis.get(key.getBytes()));
- return users.cardinality();
- }
下面的Java代码用来统计某个用户操作在一个指定多个日期的活跃用户。
- import redis.clients.jedis.Jedis;
- import java.util.BitSet;
- ...
- Jedis redis = new Jedis("localhost");
- ...
- public int uniqueCount(String action, String... dates) {
- BitSet all = new BitSet();
- for (String date : dates) {
- String key = action + ":" + date;
- BitSet users = BitSet.valueOf(redis.get(key.getBytes()));
- all.or(users);
- }
- return all.cardinality();
- }
References:
[1] Redis setbit command http://redis.io/commands/setbit
相关推荐
谈下你对 Redis 的了解? 1)Redis是一种基于键值对的NoSQL数据库(非关系型数据库);是一个key-value存储系统 2)高性能、可靠性 Redis将数据存储在内存中,读写性能高;Redis提供了 RDB和AOF持久化,可将内存...
Redis 使用说明 Redis 是一个开源的、基于内存的数据存储系统,支持多种数据结构,包括字符串、哈希、列表、集合、有序集合等。Redis 提供了丰富的命令来操作这些数据结构,满足各种应用场景的需求。 Redis 概述和...
* Bitmaps:Bitmaps是Redis的一种数据类型,使用setbit命令设置某个偏移量的值,getbit命令获取某个偏移位的值。 * HyperLoglog:HyperLoglog是Redis的一种数据类型,使用pfadd命令添加多个元素,pfcount命令统计...
在线用户统计器可以利用Redis的计数器功能,实时追踪网站或应用中的用户活动情况,为运营决策提供数据支持。自动补完程序可以通过构建高效的搜索索引,提升用户体验,加快信息检索速度。 总之,Go语言和Redis的组合...
Redis提供了监控和统计信息,可以通过`INFO`命令获取。同时,可以配置日志级别,以便在出现问题时获取更详细的日志信息。 10. **最佳实践**: 在部署和运维Redis集群时,需要遵循一些最佳实践,如合理规划槽的数量...
标题中的“利用Redis统计网站在线活跃用户的方法”指的是使用Redis这一内存数据存储系统来实时跟踪并统计网站的活跃用户数量。Redis支持多种数据结构,其中一种是基于字符串的位操作,即Bitmaps,这对于统计在线用户...
加分项:另外redis还对这几种数据结构做了扩展,如GEO对位置计算,hyperLogLog做统计,bitmaps:redis底层存储value值都是存储的二进制数据,redis提供bitmaps(位图)可以直接访问或修改底层存储的二进制数据 ...
Redis作为一个内存数据结构存储系统,支持多种数据结构,如字符串(strings)、哈希表(hashes)、集合(sets)、有序集合(sorted sets)以及位图(bitmaps)。它以纯C语言编写,运行速度快,数据持久化能力强,并...
Redis 安装简单,可以通过源码编译或使用包管理器安装。启动Redis有前台和后台两种方式,后台启动更常见。Redis 可通过`redis-cli`命令行工具进行交互,提供一系列命令用于操作数据库。 2. Redis 数据类型: - **...
6. **Bits per value (Bitmaps)**: Redis 3.0增强了Bitmaps功能,可以高效地处理位级别的操作,如设置、清除或检查特定位,这对于跟踪用户活动、状态标记等场景非常有用。 7. **地理空间索引`: Redis 3.0添加了`GEO...
你平时使用哪些工具来进行 Redis 性能监控? - **监控工具**: - `redis-cli`:官方命令行工具,可用于监控和管理Redis。 - `Redis Insight`:图形化界面工具,方便查看Redis状态。 - **诊断问题**: - 查看`...
8. **性能测试**:使用`redis-benchmark`工具进行性能测试,评估Redis在特定环境下的性能表现。 以上步骤覆盖了从安装到配置再到测试的完整流程,为初学者提供了全面的指导。通过这些内容的学习和实践,可以帮助...
- **Bitmaps扩展**:在2.8版本中,Redis增强了位图操作,支持`BITCOUNT`命令统计指定范围内的1的个数,以及`BITPOS`查找第一个0或1的位置,这在处理用户在线状态、地理位置等场景下非常实用。 - **HyperLogLog...
在数据存储方面,Redis的应用场景包括会话存储、消息队列系统、网站访问统计、实时系统指标、地理信息的处理等。 Redis之所以能处理高并发请求而不会导致数据库连接异常,是因为它采用了非阻塞I/O多路复用机制。...
可以从简单的缓存操作开始,逐步探索更复杂的使用场景,如使用Redis实现分布式锁、发布订阅系统等。此外,了解Redis的性能优化策略,如调整配置参数、内存管理等也是必要的。 总结来说,“Redis实战”这本书将引导...
在微博开放平台中,Redis作为一种内存中的数据结构存储...在微博=feed+关系+数字的模型中,Redis的实践贯穿了信息流(feed)、社交关系(关系)和数字统计(数字)的各个层面,从而保证了平台的快速响应和高效运行。
### Redis使用场景与内部数据结构详解 #### 一、Redis使用场景 Redis 是一款非常流行的开源内存数据库系统,因其高性能和灵活性而被广泛应用于多种场景之中。以下是一些常见的使用场景: 1. **缓存**: - **本地...
Redis提供的客户端工具`redis-cli`可以帮助开发者进行命令行交互,进行数据操作和调试。此外,Redis支持通过输入`help <command>`或者`help @<group>`来获取特定命令的帮助信息,极大地便利了开发人员的学习和使用...