位图(也称为位数组,位向量等)是当需要将大域的布尔信息映射到紧凑表示时立即弹出的数据结构。每当内存空间非常宝贵时,它就是一种非常流行的数据结构:OS内核(内存页面,inode等),数字成像等。

 

Redis是一种内存数据结构服务器,它为位操作操作提供支持。但是,Redis中的位图没有特殊的数据结构。相反,基本的Redis结构支持位级操作:字符串。现在,Redis字符串的最大长度为512 MB。因此,Redis可以映射为位图的最大域是2 32(512 MB = 2 29字节= 2 32位)。

Redis中的位相关操作有两种:恒定时间(O(1)),例如,获取/设置特定位的操作和基本上对一组位操作的O(N)操作。在这些情况下,N是操作需要处理的位长度。我们来看一些例子。

命令

除了操作密钥本身的运算符之外,BITOP运算符还用于在多个密钥之间进行逐位逻辑运算。

内幕

由于位图操作没有自己的数据结构,因此没有特定的数据结构可供描述。Redis字符串本身实现为二进制安全字符串。Redis字符串数据结构在内部称为简单动态字符串(SDS)。它本质上是一个本地char [],带有一些额外的簿记信息。实施细节可以在这里找到。

位图函数的实现位于文件bitops.c中

PS:鉴于位操作算法对关键操作系统和图形功能的重要性,大多数架构都为此类操作提供了特殊指令。阅读各种有趣的计算机算术算法的好地方是经典的Hacker's Delight

 

应用

这个流行的GetSpool博客是使用位图在大型数据集上进行实时分析的一个很好的例子。它也是位图的经典用例的一个例子:将极大域的布尔信息存储到(相对)小空间中,同时保持良好的性能。

大小通常是真正大型位图的关注点,因为大多数有用的操作都是O(N)。为了避免使用大密钥,Redis文档建议将大密钥分成多个较小的密钥。在关键变大之前,BITCOUNT表现仍然可以接受。此时,建议分割键或使用范围参数逐步查询。处理慢BITOP操作的建议是在slave上运行它。因此,一般来说,处理中等大小的密钥并通过将密钥分成多个密钥来规划未来的潜在增长是有意义的。

 Redis设置与Redis位图

Redis集提供的功能性质和位图操作类似。因此,这两种方法中哪一种更好会让人感到困惑。嗯,这实际上取决于用例的确切性质。显然,此讨论仅对集合和位图可以实现的操作类型有效。

Redis集合通常效率很高,并且可以很好地扩展,并且应该是所选择的数据结构,直到它的大小变得难以维持。Redis集也更易于管理,程序和调试适用于大多数应用程序。不应低估集合的易用性:操作位图的代码通常难以阅读,理解,调试和维护。即使域非常大,集合仍可能是合适的。例如,如果应用程序旨在跟踪对流行的电子商务站点的每日访问,则结果可能仍然适合于集合,因为通常仅5-10%的整个用户群将每天访问该站点。对于预计每天登录60%的用户群的网站来说,这显然会发生变化。然后,鉴于在大量密钥上的逻辑位操作的大小和性能,位图变得更相关。Redis集还具有不必将ID映射到位偏移的独特优势。同样,如果您的值来自大于2的域32然后Redis集必须比找出分割域的域的机制更容易使用。

针对MOOC的分析

这是一个可以应用Redis位图操作的地方的炮制(但足够真实!)示例。比如说,您正在运行一个非常受欢迎的在线MOOC,数十万学生已经注册了该MOOC。促进课程的学术团队需要一个仪表板,他们可以看到学生进度的实时状态以及注册学生的一般背景。您决定通过Redis位图操作实现此功能。这是一步一步的方法。

  1. 创建计划以在学生ID和位图偏移之间进行映射。它可能就像ID是位图中的偏移一样简单。
  2. 课程开始后,创建并填充各种与人口统计相关的位图。例如,从同一所大学,教育水平,性别等入读其他MOOC的学生。
  3. 现在,随着课程的进展,您可以创建新的位图来记录课程进度。例如,完成了第1周所有讲座的学生,完成第1周所有作业的学生。
  4. 现在,基于这些键创建实时分析将是一个非常简单的练习,可以在拖放UI上完成。例如
  • 一位教授想看看有多少学生在第1周(A)观看讲座但没有完成第1周(B)的作业:操作员:BITOP。操作:A AND(非B)。
  • 完成第1周(A),第2周(B),第3周(C)和第4周(D)的所有作业的学生:操作员:BITOP。操作A和B和C和D.说,这些是通过该课程的人。
  • 所有通过该课程的男学生(M)(如上所述,比如P):操作员:BITOP。操作:M和P.
  • 通过该课程的学生人数:BITCOUNT P.

类似地,可以将任意数量的有趣群组设置为位图,并在其上运行这样的排列。

 

10-07 18:30