Redis 精确去重计数 —— 咆哮位图

使用Roaring Bitmap返回海量数据 如果你需要处理海量数据(例如千万级的 ID 数据)并返回咆哮位图(Roaring Bitmap),可以使用库。Roaring Bitmap 是一种高效压缩的位图数据结构,特别适合处理大规模整数集合。以下是一个 Java 示例,展示如何使用 RoaringBitmap 处理千万级 ID 数据并返回咆哮位图。 阅读详情

如果要统计一篇文章的阅读量,可以直接使用 Redis 的 incr 指令来完成。如果要求阅读量必须按用户去重,那就可以使用 set 来记录阅读了这篇文章的所有用户 id,获取 set 集合的长度就是去重阅读量。但是如果爆款文章阅读量太大,set 会浪费太多存储空间。这时候我们就要使用 Redis 提供的 HyperLogLog 数据结构来代替 set,它只会占用最多 12k 的存储空间就可以完成海量的去重统计。但是它牺牲了准确度,它是模糊计数,误差率约为 0.81%。

那么有没有一种不怎么浪费空间的精确计数方法呢?我们首先想到的就是位图,可以使用位图的一个位来表示一个用户id。如果一个用户id是32字节,那么使用位图就只需要占用 1/256 的空间就可以完成精确计数。但是如何将用户id映射到位图的位置呢?如果用户id是连续的整数这很好办,但是通常用户系统的用户id并不是整数,而是字符串或者是有一定随机性的大整数。

我们可以强行给每个用户id赋予一个整数序列,然后将用户id和整数的对应关系存在redis中。

$next_user_id = incr user_id_seq
set user_id_xxx   $next_user_id
$next_user_id = incr user_id_seq
set user_id_yyy  $next_user_id
$next_user_id = incr user_id_seq
set user_id_zzz   $next_user_id

有了这个映射关系,我们就很容易构造出每一篇文章的阅读打点位图,来一个用户,就将相应位图中相应的位置为一。如果位从0变成1,那么就可以给阅读数加1。这样就可以很方便的获得文章的阅读数。

而且我们还可以动态计算阅读了两篇文章的公共用户量有多少?将两个位图做一下 AND 计算,然后统计位图中位 1 的个数。同样,还可以有 OR 计算、XOR 计算等等都是可行的。

问题又来了!Redis 的位图是密集位图,什么意思呢?如果有一个很大的位图,它只有最后一个位是 1,其它都是零,这个位图还是会占用全部的内存空间,这就不是一般的浪费了。你可以想象大部分文章的阅读量都不大,但是它们的占用空间却是很接近的,和哪些爆款文章占据的内存差不多。

看来这个方案行不通,我们需要想想其它方案!这时咆哮位图(RoaringBitmap)来了。

它将整个大位图进行了分块,如果整个块都是零,那么这整个块就不用存了。但是如果位1比较分散,每个块里面都有1,虽然单个块里的1很少,这样只进行分块还是不够的,那该怎么办呢?我们再想想,对于单个块,是不是可以继续优化?如果单个块内部位 1 个数量很少,我们可以只存储所有位1的块内偏移量(整数),也就是存一个整数列表,那么块内的存储也可以降下来。这就是单个块位图的稀疏存储形式 —— 存储偏移量整数列表。只有单块内的位1超过了一个阈值,才会一次性将稀疏存储转换为密集存储。

咆哮位图除了可以大幅节约空间之外,还会降低 AND、OR 等位运算的计算效率。以前需要计算整个位图,现在只需要计算部分块。如果块内非常稀疏,那么只需要对这些小整数列表进行集合的 AND、OR 运算,如是计算量还能继续减轻。

这里既不是用空间换时间,也没有用时间换空间,而是用逻辑的复杂度同时换取了空间和时间。

咆哮位图的位长最大为 2^32,对应的空间为 512M(普通位图),位偏移被分割成高 16 位和低 16 位,高 16 位表示块偏移,低16位表示块内位置,单个块可以表达 64k 的位长,也就是 8K 字节。最多会有64k个块。现代处理器的 L1 缓存普通要大约 8K,这样可以保证单个块都可以全部放入 L1 Cache,可以显著提升性能。

如果单个块所有的位全是零,那么它就不需要存储。具体某个块是否存在也可以是用位图来表达,当块很少时,用整数列表表示,当块多了就可以转换成普通位图。整数列表占用的空间少,它还有类似于 ArrayList 的动态扩容机制避免反复扩容复制数组内容。当列表中的数字超出4096个时,会立即转变成普通位图。

用来表达块是否存在的数据结构和表达单个块数据的结构可以是同一个,因为块是否存在本质上也是 0 和 1,就是普通的位标志。

但是 Redis 并没有原生支持咆哮位图这个数据结构啊?我们该如何使用呢?

Redis 确实没有原生的,但是咆哮位图的 Redis Module 有。

https://github.com/aviggiano/redis-roaring

这个项目的 star 数量并不是很多,我们来看看它的官方性能对比

下面我们来观察一下源代码看看它的内部结构是怎样的

// 单个块
typedef struct roaring_array_s {
    int32_t size;
    int32_t allocation_size;
    void **containers;  // 指向整数数组或者普通位图
    uint16_t *keys;
    uint8_t *typecodes;
    uint8_t flags;
} roaring_array_t;

// 所有块
typedef struct roaring_bitmap_s {
    roaring_array_t high_low_container;
} roaring_bitmap_t;

#define BITSET_CONTAINER_TYPE_CODE 1
#define ARRAY_CONTAINER_TYPE_CODE 2
#define RUN_CONTAINER_TYPE_CODE 3
#define SHARED_CONTAINER_TYPE_CODE 4

而 SHARED 类型用于在多个咆哮位图之间共享块,它还提供了写复制功能。当这个块被修改时将会复制出新的一份。

咆哮位图的计算逻辑还有更多的细节,我们后面有空再继续介绍。

640?wx_fmt=png
redis-roaring:Redis咆哮的位图 重传 Redis咆哮的位图 介绍 该项目使用库为Redis实现咆哮位图命令。 根据微基准测试,这些命令可以与Redis的O(1)操作本机位图具有相同的性能,并且O(N)调用的,同时比未压缩的对等方消耗的内存更少(基准测试未决)。 拉请求是受欢迎的。 依存关系 CRoaring(此redis模块使用的位图压缩库) cmake(编译源代码所需的构建工具) redis(集成测试所需的服务器) hiredis(性能测试所需的redis客户端库) 已知的问题 该库仅适用于(例如,计数最大为4294967296的数字) 入门 $ git clone https://github.com/aviggiano/redis-roaring.git $ cd redis-roaring/ $ configure.sh $ cd dist $ ./redis-server ./redis.conf 立即下载

相关推荐

VMware虚拟机安装MS-DOS 7.10教程

dos安装教程dos版本7.10附下载链接。

Minecraft_xiaole的博客 1万+

Roaring位图具有更好的位图性能

翻译论文,与自己的理解,如有不对的,欢迎评论指出。 [Better bitmap performance with Roaring bitmaps](https://arxiv.org/abs/1402.6407) 作者:Samy Chambi, Daniel Lemire, Owen Kaser, Robert Godin

一本郑经的程序员 886

HexView 脚本自动化工具:从刷写文件处理到批量转换实战

本文详细介绍了如何利用HexView脚本自动化工具高效处理嵌入式刷写文件。通过实战演示,文章展示了如何使用bat脚本实现S19、HEX等格式文件的剪切、填充、合并与批量转换,构建自动化流水线,从而显著提升汽车电子等领域的开发与生产效率。

weixin_29237635的博客 355

位图 & 咆哮位图

这就是为什么在现代大数据系统中,Roaring Bitmap 能够取代传统位图成为标准解决方案的原因。位图使用一个比特数组来表示集合。桶0x0003中有很多元素,如。要表示最大值为12的集合,需要。元素数量 ≤ 4096。(在桶0x0001中)元素数量 > 4096。位设为1,否则为0。固定 8192 字节。

小小博客 335

MBIST --- PATR1.Memorybist测试原理

mem bist作为现在design设计中不可或缺的DFT设计内容,越发重要。本章节主要介绍mem bist组成部分,测试的原理以及注意事项。

sinat_27691203的博客 1万+

孤读paper——《GhostNet:More Features from Cheap Operations》

《GhostNet:More Features from Cheap Operations》   发现一个点并解决就是一篇CVPR,该文章主要发现了优秀的网络的特点是feature map提取过程中的冗余性,这种冗余性体现在很多成对的feature map间很像,就好像彼此的“ghost”,而这种特征冗余性对于理解图像来说还是必要的,所以文章把feature map分为两种,一种是本质特征,一...

雄关漫道真如铁 而今迈步从头越 5150

【玩转Redis】一文看懂 Redis的5种常用数据结构和4种特殊数据结构!

简介 我们在实现一些业务的时候,做一些比较特有的需求,用传统的DB去做会很繁琐,比如实现一个微信记步排行,频繁访问封锁IP,秒杀等等需求,而利用Redis里面的数据结构特性,能相对便携的实现这些需求。 详解 1. String value 值可以是字符型,也可以是数字。 其实没有什么特别的特点,正常的持久化那些基本操作,get set 然后获取字符串长度,让字符串拼接等 如果是数字的话,可以incre decre 计数功能 常用命令: get、set、incr、decr、mget等 应

OxYGC 1553

WGCNA样本量不够怎么办?5种替代方案帮你解决小样本基因共表达分析难题

本文针对WGCNA样本量不足的问题,提供了5种科学替代方案,包括CEMiTool、参数调整、多组学数据整合、机器学习特征提取和公共数据利用。这些方法帮助研究者在小样本条件下仍能进行可靠的基因共表达分析,特别适用于罕见病和珍贵临床样本研究。

weixin_42554042的博客 301

Redis精确去重计数方法(咆哮位图)

这篇文章主要给大家介绍了关于Redis精确去重计数方法(咆哮位图)的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Redis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧 前言 如果要统计一篇文章的阅读量,可以直接使用 Redis 的 incr 指令来完成。如果要求阅读量必须按用户去重,那就可以使用 set 来记录阅读了这篇文章的所有用户 id,获取 set...

u011250186的博客 792

Three 之 three.js (webgl)绘制物体模型尺寸虚线包围框工具简单封装 DashLinesBoxTool

Three js 开发的一些知识整理,方便后期遇到类似的问题,能够及时查阅使用。本节介绍, three.js (webgl) 中绘制物体模型尺寸虚线包围框工具简单封装 DashLinesBoxTool,主要是给实物绘制线框,有点像AI 识别正方形包裹框的效果。其中,如果有不足之处,欢迎指出,或者你有更好的方法,欢迎留言。

仙魁XAN 2106

华为OD机试新系统真题【迷宫相遇】

华为OD机试 新系统真题【迷宫相遇】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【迷宫相遇】多语言题解。

qq_45776114的博客 764

redis统计用户日活量_Redis精确去重计数方法(咆哮位图)

前言如果要统计一篇文章的阅读量,可以直接使用 Redis 的 incr 指令来完成。如果要求阅读量必须按用户去重,那就可以使用 set 来记录阅读了这篇文章的所有用户 id,获取 set 集合的长度就是去重阅读量。但是如果爆款文章阅读量太大,set 会浪费太多存储空间。这时候我们就要使用 Redis 提供的 HyperLogLog 数据结构来代替 set,它只会占用最多 12k 的存储空间就可以完...

weixin_34556619的博客 593

【YOLOv26 源码深度解析】第三章:YOLOv26特征融合(Neck)模块

路径聚合网络作为YOLOv26 Neck部分的核心组件,在继承特征金字塔网络(FPN)自顶向下语义传播能力的基础上,引入了自底向上的路径增强机制,构建起双向跨层特征融合体系。该架构通过建立多尺度特征间的双向信息流,有效缓解了深层网络中细节信息逐层衰减的问题,使得模型在保持高层语义理解能力的同时,能够精确定位不同尺度的目标实例。跨层深度监督的另一优势在于增强特征的尺度适应性。对于来自上层路径的特征与横向连接的特征,融合过程首先对各路特征进行加权,随后进行归一化处理,最终通过加法或拼接操作生成融合特征。

u012133341的博客 518

多个字段去重_Redis 精确去重计数 —— 咆哮位图

如果要统计一篇文章的阅读量,可以直接使用 Redis 的 incr 指令来完成。如果要求阅读量必须按用户去重,那就可以使用 set 来记录阅读了这篇文章的所有用户 id,获取 set 集合的长度就是去重阅读量。但是如果爆款文章阅读量太大,set 会浪费太多存储空间。这时候我们就要使用 Redis 提供的 HyperLogLog 数据结构来代替 set,它只会占用最多 12k 的存储空间就...

weixin_32579395的博客 184

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

列表去重_Redis 精确去重计数 —— 咆哮位图

如果要统计一篇文章的阅读量,可以直接使用 Redis 的 incr 指令来完成。如果要求阅读量必须按用户去重,那就可以使用 set 来记录阅读了这篇文章的所有用户 id,获取 set 集合的长度就是去重阅读量。但是如果爆款文章阅读量太大,set 会浪费太多存储空间。这时候我们就要使用 Redis 提供的 HyperLogLog 数据结构来代替 set,它只会占用最多 12k 的存储空间就可以完成海...

weixin_39831991的博客 148

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Redis 精确去重计数 —— 咆哮位图

如果要统计一篇文章的阅读量,可以直接使用 Redis 的 incr 指令来完成。如果要求阅读量必须按用户去重,那就可以使用 set 来记录阅读了这篇文章的所有用户 id,获取 set 集合的长度就是去重阅读量。但是如果爆款文章阅读量太大,set 会浪费太多存储空间。这时候我们就要使用 Redis 提供的 HyperLogLog 数据结构来代替 set,它只会占用最多 12k 的存储空间就可以完成海...

weixin_45189747的博客 282

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

两个字段位置相反去重_Redis 精确去重计数 —— 咆哮位图

如果要统计一篇文章的阅读量,可以直接使用 Redis 的 incr 指令来完成。如果要求阅读量必须按用户去重,那就可以使用 set 来记录阅读了这篇文章的所有用户 id,获取 set 集合的长度就是去重阅读量。但是如果爆款文章阅读量太大,set 会浪费太多存储空间。这时候我们就要使用 Redis 提供的 HyperLogLog 数据结构来代替 set,它只会占用最多 12k 的存储空间就可以完成海...

weixin_39806679的博客 285

两个字段位置相反去重_Redis 精确去重计数 —— 咆哮位图

如果要统计一篇文章的阅读量,可以直接使用 Redis 的 incr 指令来完成。如果要求阅读量必须按用户去重,那就可以使用 set 来记录阅读了这篇文章的所有用户 id,获取 set 集合的长度就是去重阅读量。但是如果爆款文章阅读量太大,set 会浪费太多存储空间。这时候我们就要使用 Redis 提供的 HyperLogLog 数据结构来代替 set,它只会占用最多 12k 的存储空间就...

weixin_39932939的博客 110

java位图去重_Redis系列(3) Bloom/BitMap/Geo

全文代码及安装均基于 Redis5.01.Redis中的布隆过滤器 (验证某X是否在某Y中, 防缓存穿透)2.Redis去重计数 (大批量数据)3.Redis实现分布式计数器 (限流 & 接口请求次数统计)4.Redis GEO (附近的人, 商店)1.Redis中的布隆过滤器 (验证某X是否在某Y中, 防缓存穿透)2.Redis去重计数 (大批量数据)2.1 HyperLogLog (模...

weixin_32940203的博客 724

Redis去重计数的四种实现方式

博客还是要写的, 知识还是要整理的. 不常用的东西不整理, 到最后就只剩下一个名词.

cs958903980的博客 3664

RoaringBitmap 项目推荐

RoaringBitmap 项目推荐 RoaringBitmap RoaringBitmap/RoaringBitmap: RoaringBitmap是一个高效的位图数据结构库,特别适合于大数据集下的集合操作,常用于数据库索引、搜索引擎等领域。 ...

gitblog_00498的博客 442

【redis】bitmap技术解析:redis与roaringBitmap

然后再看这个好理解一些。bitmap的表象意义是,使用一个01标识位来表示是否的状态,可以达到节省空间和高效判定的效果。在我们的实际工作中,也有着许多的应用场景,相信了解bitmap定会给你带来一些额外的收获。

九师兄 649

Redis bitmap、hyperlog、布隆过滤器、RoaringBitmap原理应用场景与日活的统计的具体应用

缺点: 1.空间占用大2.统计逻辑复杂,比如统计最近 30 天用户的累计活跃天(每个用户在 30 天里有 N 天使用 app,N 为 1-30,然后将月活跃用户的 N 天加总)?统计最近 7 天的用户累计使用时长?统计最近 30 天有播放的累计用户数?统计最近 30 天活跃用户有多少在最近 30 天里有连续 3 天及以上活跃?统计 28 天前活跃用户的 1、3、7、14、28 天留存率?3、mysql性能消耗大, 4、以上统计逻辑可扩展性差,由于数据分析经常进行探索性分析,上面传统方案能解决上面几个问题,但

S_ZaiJiangHu的博客 4574

Redis bitmap数据格式优化 (RoaringBitmap)

1. Key-Value 存储 尝试插入1kw条数据, key为设备MD5值, value为1, 此时Redis中存在1kw条key-value键值对. 通过info指令查看内存占用: 1kw数据key-value占用内存 结论: 可以看到, 1kw条MD5数据占用Redis内存约为892MB; 这还只是一个客户上传的人群包, 如果上传的人群包较多, 则Redis需要大量的集群部署, 成本会及其大; 无论是采用List, Hash, Set等结构都会出现这种情况, 所以Redis的这些数据

琪琪的博客 3675
上一篇: 分布式系统的可靠性指的是什么 —— 你可能从来就没有认真思考过
下一篇: 深入理解 hash 结构的另一种形式 —— 开放地址法
codehole_
博客等级 码龄7年 34粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值