BloomFilter使用和redis的setbit、bitcount实现用户上线次数统计

布隆过滤器的应用 — 实现”活跃账号设备比异常“检测 在一个app的登录场景中,有两个重要的信息:账号和设备号 设备号标识一个被安装的app,在app安装时生成,如果卸载了重新安装则会生成新的设备号。 假设有个需求,需要检测一个时间窗口内活跃账号和设备比是否在合理范围内,如果不在合理范围内则告警提醒。 一般的方案有下面两种: 方案 特点 内存set 优点:性能好,缺点:存储数据有限 数据库 优点:可以存储更多数据,缺点:性能相对差,需要维护数据的清除逻辑 这两种方案各有其优缺点。 那么,如果我既追求性能,又追求存储更多的数据,有办法吗 阅读详情

简介

BloomFilter过滤器可以快速判断某值是否存在,虽然不一定准确,但是相对而且它既快速而且又相对准确。
Bloom Filter没有False Negative,即判断某元素时否在Bloom Filter中时,如果返回False, 则可以肯定该元素不在集合中,但是Bloom Filter存在False Positive, 即如果返回True, 并不能完全肯定元素就在集合中,但是有很大的概率确实在集合中。

BloomFilter算法

  • 简介:布隆过滤器实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
  • 原理:当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。
  • 优点:相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常数(O(k))。而且它不存储元素本身,在某些对保密要求非常严格的场合有优势。
  • 缺点:一定的误识别率和删除困难。
    结合以上几点及去重需求(容忍误判,会误判在,在则丢,无妨),决定使用BlomFilter。

如何根据输入元素个数n,确定位数组的大小m和哈希函数的个数k?
https://blog.youkuaiyun.com/qq_18495465/article/details/78500472
在这里插入图片描述
Guava中的Bloom Filter, Bloom Filter是一种省内存的基于概率的数据结构,可判断一个元素是否在集合中。

Bloom Filter实现思路

位数组和k个散列函数

1.位数组
初始状态时,BloomFilter是一个长度为m的位数组,每一位都置为0。这个结构刚和和redis的bitMap相同,当然也和Java自带的bitSet结构相似,唯一不同在于一个中间件存储数据量多,一个Java内存的数据量少。
在这里插入图片描述

2.添加元素(k个独立的hash函数)
添加元素时,对x使用k个哈希函数得到k个哈希值,对m取余,对应的bit位设置为1。
在这里插入图片描述
这里和Java的单个hash不同,它会经历2个以上不同质数hash函数,对应到不同的bit位,如上图两个个hash函数值对应的x1,x2分别对应到不同的bit位。多层hash的目的就在于避免单次hash造成的bit位相同,从而影响判断结果,因此它也无法保证结果是一定的,只能做到尽量符合预期结果。

3.判断元素是否存在
判断y是否属于这个集合,对y使用k个哈希函数得到k个哈希值,对m取余,所有对应的位置都是1,则认为y属于该集合(哈希冲突,可能存在误判),否则就认为y不属于该集合。
图中y1不是集合中的元素,y2属于这个集合或者是一个false positive。
在这里插入图片描述
二进制数据的bit位异或操作很容易就能判断是全1的真还是假,因此速度很快,不用像字符串判断中需要一个一个的做对比。当然问题依然存在就是如果两个不同字符串多次hash的值依然相同的问题,只要数据量足够大这样的结果仍然会出现,只是概率问题。因此BloomFilter只能做到尽量合乎预期而不能做到完全一致。

BloomFilter有以下参数:

  • m 位数组的长度
  • n 加入其中元素的数量
  • k 哈希函数的个数
  • f False Positive失败概率

BitMap是什么

就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间。

Redis中的BitMap
Redis从2.2.0版本开始新增了setbit,getbit,bitcount等几个bitmap相关命令。虽然是新命令,但是并没有新增新的数据类型,因为setbit等命令只不过是在set上的扩展。

setbit基本操作

redis> SETBIT bit 0 1  # 0001
(integer) 0

redis> GETBIT bit 3 1 # 1001
(integer) 1

redis> GETBIT bit 100   # bit 默认被初始化为 0
(integer) 0

redis> BITCOUNT bits  # bit中又多少个1
(integer) 1


BITOP operation resultKey key1 key2。operation 是位运算的操作,有 AND,OR,XOR,NOT。resultKey 是把运算结构存储在这个 key 中,key1 和 key2 是参与运算的 key,参与运算的 key 可以指定多个。

setbit的offset是用大小限制的,在0到 232(最大使用512M内存)之间,即0~4294967296之前,超过这个数会自动将offset转化为0,因此使用的时候一定要注意。

https://www.runoob.com/redis/strings-setbit.html

使用场景

使用场景一:用户签到
使用场景二:统计活跃用户
使用场景三:用户在线状态
用户日活,月活,留存率的统计

统计活跃用户为例
每个用的key:"REPORT:1"对应的bit位010001中的1则对应具体某天的签到状态
总共签到天数:bitcount REPORT:1
时间段内的签到天数:获取index为[start,end]的bit位统计1的个数
判断当天是否已经签到:getbit REPORT:1 offset


/**
 * @program: demo
 * @description: redisTest
 * @author: Bamboo zjcjava@163.com
 * @create: 2019-10-13 23:07
 **/

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class SpringRedisTest {

    @Autowired
    private RedisClient redisClientCache;

    private JedisPool jedisPool;

    @Test
    public  void test() {

    // 用户ua的活跃时间
        addCount("ua","20191011");
        addCount("ua","20191012");
        addCount("ua","20191013");
        addCount("ua","20191014");

        
        uniqueCount("ua","20191011");
        uniqueCount("ua","20191009");
        uniqueCount("ua","20191011","20191012");//两个日期内的活跃次数
        totalCount("ua");//总活跃次数
    }


    //某个用户在某天是否活跃
    public void addCount(String action, String date) {
        Jedis jedis = redisClientCache.getJedis();
        String key = "REPORT:"+action ;
        jedis.setbit(key.getBytes(),Long.valueOf(date),true);
        jedis.close();
    }

    //判断某个用户操作在某天是否活跃
    public void uniqueCount(String action, String date) {
        Jedis jedis = redisClientCache.getJedis();
        String key = "REPORT:"+action ;

        System.out.println("某个用户操作在某天是否是活跃用户"+date+"--- " +jedis.getbit(key.getBytes(),Long.valueOf(date)));
        jedis.close();
    }


    //下面的Java代码用来统计某个用户操作在一个指定多个日期的活跃次数。
    public void uniqueCount(String action, String... dates) {
        Jedis jedis = redisClientCache.getJedis();
        BitSet all = new BitSet();
        String key = "REPORT:"+action ;
        BitSet users = BitSet.valueOf(jedis.get(key.getBytes()));
        all=users.get(Integer.valueOf(dates[0]),Integer.valueOf(dates[1])+1);
        jedis.close();
        System.out.println("多个日期的活跃次数--- " +all.cardinality());
    }

    //统计某个用户总共活跃次数。
    public void totalCount(String action) {
        Jedis jedis = redisClientCache.getJedis();
        String key = "REPORT:"+action ;
        jedis.close();
        System.out.println("总活跃次数--- " +jedis.bitcount(key.getBytes()));
    }

}


使用Redis统计UV数据-HyperLogLog
pfadd:新增
pfcount:获取总数

未完待续…进行中

参考资料

https://blog.youkuaiyun.com/lglgsy456/article/details/39394961
https://blog.youkuaiyun.com/z834410038/article/details/73882000
segmentfault.com/a/1190000008188655
my.oschina.net/go4it/blog/1975878
blog.youkuaiyun.com/jinjiating/article/details/91885978

Redis高频面试题解析与Java实战指南 Redis作为高性能内存数据库,其核心原理基于内存存储与多种数据结构实现。通过String、Hash等数据结构支持不同业务场景,配合RDB/AOF持久化机制保障数据安全。在分布式系统中,Redis常用于实现缓存穿透防护、分布式锁等高并发解决方案,其集群模式支持水平扩展应对大数据场景。本文结合Java代码示例,详细解析Redis在面试中的高频考点,包括数据结构应用、持久化配置、性能优化等实战技巧,帮助开发者深入理解Redis技术体系并提升工程实践能力。 阅读详情

相关推荐

从MATLAB代码入手:手把手教你复现OTFS调制解调核心模块(附完整函数解析)

本文详细解析了OTFS调制解调技术在MATLAB中的实现方法,包括核心模块如ISFFT变换、海森堡变换及MP检测算法的代码实现。通过完整的函数解析和性能验证框架,帮助通信工程师快速掌握这一前沿技术,提升在高速移动场景下的通信系统设计能力。

weixin_42568801的博客 318

【算法】BloomFilter概念和原理以及业务中的应用场景

BloomFilter概念和原理以及业务中的应用场景

互联网小阿祥 1209

pi-star图形界面安装指南

pi-star图形界面安装指南,MMDVM热点安装,树莓派3B+热点

blueisman的专栏 1908

BitMap、BloomFilter详解以及应用场景

一、Bit-Map算法     先看看这样的一个场景:给一台普通PC,2G内存,要求处理一个包含40亿个不重复并且没有排过序的无符号的int整数,给出一个整数,问如果快速地判断这个整数是否在文件40亿个数据当中? 问题思考:      40亿个int占(40亿*4)/1024/1024/1024 大概为14.9G左右,很明显内存只有2G,放不下,因此不可能将这40亿数据放到内存中计算。要快速...

bigdata_player 1611

Python Trimesh库实战:5分钟搞定STL文件解析与3D模型可视化

本文介绍了如何使用Python的Trimesh库快速解析STL文件并进行3D模型可视化。通过简洁的代码示例,演示了从环境搭建、模型加载、几何数据提取到基础变换和批量处理的核心流程,帮助开发者和工程师在5分钟内高效完成3D数据处理与可视化任务。

weixin_32005771的博客 158

Deepfake检测模型-PyDeepFakeDet项目复现实验报告-深度学习

该实验是对于https://github.com/wangjk666/PyDeepFakeDet模型的复现。PyDeepFakeDet 是一款集成的、可扩展的 Deepfake 检测工具。目标是提供最先进的 Deepfake 检测模型以及用于在常用 Deepfake 数据集上训练和评估新模型的接口。

一位不是很硕的鉴伪方向硕士 5494

布隆过滤器核心原理&redisBitMap 分布式实现

Data structures are nothing different. They are like the bookshelves of your application where you can organize your data. Different data structures will give you different facility and benefits. To ...

风吟 3824

lammps案例:堆垛层错能的计算

大家好,我是小马老师。 本文介绍如何使用lammps计算晶体的堆垛层错能。 正常晶体中的原子按照一定的规律排列,原子面按ABCABC……的顺序排列,如下图所示: 当某个原子面被抽出后会形成堆垛层错,如图中的蓝色原子层被抽出,原子面排列变为ABCBCA……: 可通过计算堆垛层错能形成前后的能量差计算堆垛层错能,计算公式为: E0为初始能量 Ef为删除一个原子面后的能量 A为界面面积 下面分享一个lammps计算堆垛层错能的in代码,本代码由Richard Glaze完成,本文稍作修改并进行了注释,以供初

lammps_jiayou的博客 5434

Redis--各个数据类型最大存储量

Strings类型:一个String类型的value最大可以存储512MLists类型:list的元素个数最多为2^32-1个,也就是4294967295个。Sets类型:元素个数最多为2^32-1个,也就是4294967295个。Hashes类型:键值对个数最多为2^32-1个,也就是4294967295个。Sorted sets类型:跟Sets类型相似。...

sinat_27143551的博客 6万+

金三银四!风控建模岗面试题库大全:从理论到实战避坑指南

风控建模面试大全

阿黎逸阳的博客 767

NR TA

这篇是NR TA的笔记,之前有对R17 NTN TA进行了简单总结,但是也仅仅局限在NTN部分,其他TA基本过程没有涉及,这篇是针对R16版本协议对NR TA相关内容做的总结。和PUSCH power control过程类似,NR TA也可以分为开环 和闭环调整,相关内容分散在38.300,38.211,38.213,38.321,38.133和38.331。后面就按照38.300 TA相关概念,38.211中有关TA定义,38.213 TA 相关内容,38.321 TA控制过程,38.133 Timi

ModemProtocol的博客 768

分布式缓存Redis之bitmap、setbit

写在前面  本学习教程所有示例代码见GitHub:https://github.com/selfconzrr/Redis_Learning基本语法:1)SETBITredis 127.0.0.1:6379> setbit KEY_NAME OFFSET VALUE //该命令用于对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。时间复杂度O(1)  在redis中,存储的字符串都是

ZhangRui的博客 2万+

AI智能体丨使用Coze一键生成爆款书单视频,3个月内获赞131.1w!(附保姆级教程)

这篇教程详细介绍了如何使用扣子(Coze)平台的AI智能工作流批量制作爆款书单视频。通过自动化流程,只需1-2分钟即可生成45-50秒的书单视频,效率提升近百倍。工作流包含文案生成、音频合成、图片素材获取、视频剪辑等全流程,支持随机生成8本书单、自动提取金句、智能配音等功能。教程提供了完整的操作步骤,包括剪映草稿配置、特效添加等细节,并附体验链接和示例效果。最终生成的视频包含书单展示、金句字幕、背景音乐等元素,适合书单号运营者快速批量产出内容。

李同学Lino的博客 2353

Redis 命令 setbit、bitcount、getbit、bitop

注:setbit 是按照 bit 的位置来设置1的,从左开始,第一位offset为0,第二位为1,而bitcount 的start 和 end 是 基于byte的, 即 bitcount xx 0 2 的话,计算的是bit offset从0到15的2个byte中bit为1的数量 1.SETBIT key offset value   对 key 所储存的字符串值,设置或清除指定偏移量上的...

z69183787的专栏 1716

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Redis中setbit和bitcount的注意细节

setbit 可以理解是一个位数组,至于这个数组有多大,redis中bit映射被限制在512MB之内,所以最大是2^32。 也就是在这样一个位数组上存0或者是1 ,可以结合bloomFilter的应用场景理解位数组的用法,将字符串使用一种合适哈希函数映射到不同的bit位上(2^32足够的大,可以满足需求)

会呼吸的鱼 6089

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Redis中bitmap使用详解

Redis除了提供5种基本数据结构之外,还在这些基本数据结构之上提供了一些高级功能,如geo、hyperloglog、pub\sub,本文主要介绍了bitmap的使用方式和常见业务场景。

weixin_41715893的博客 3862

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

✅技术社区—使用Redis BitMap实现签到与查询历史签到以及签到统计功能

签到是一个很常见的功能,如果使用数据库实现,那么用户一次签到,就是一条记录,假如有100万用户,平均每个用户每年签到次数为30次,则这张表一年的数据量为 3000 万条,一般签到记录字段不会太多一条数据按照30字节算,一年就是858.3MB左右,但是对于签到信息查询是比较频繁的,如查询当天是否签到、查询用户近7天签到记录、查询用户近30天签到记录、统计用户签到次数,如果这些查询都要去签到表查询那么数据库压力是非常大的,而且考虑到数据量会不断增长,这里使用Redis BitMap 实现高效的签到与统计。

weixin_62079735的博客 1763

Redis->Redis bitmap(位图) 相关操作 与 用户统计

1.分布式缓存Redis之bitmap、setbit https://blog.youkuaiyun.com/u011489043/article/details/78990162 2.Redis的位图bitmap https://blog.youkuaiyun.com/chengqiuming/article/details/79118089     Redis 中有有一种数据结构,非常便于位图级别的统计方...

迎难而上 4067

初识redis的bitmap

初识redis的bitmap 转载:https://blog.youkuaiyun.com/u011489043/article/details/78990162 写在前面   本学习教程所有示例代码见GitHub:https://github.com/selfconzrr/Redis_Learning 基本语法: 1)SETBIT /...

stay hungry ! stay foolish! 514

Redis7高级之简单实现布隆过滤器BloomFilter + bitmap(七)

简单实现布隆过滤器BloomFilter + bitmap,对于布隆过滤器和 bitmap的讲解并且两者结合实现springboot + redis + mybatis的整合

m0_55993923的博客 2034

Redis面试题分享三十七:聊聊 Redis 的bitmap?

大家都知道redis的五种常用类型string、hash、list、set、zset 那除此之外,redis还有一些特殊类型,bitmap就属于其中一种,接下来就对bitmap做一下详细说明。Redis 的位图不是实际的数据类型,而是在字符串类型上定义的一组面向位的操作。因为字符串是二进制安全的blob,它们的最大长度为512 MB,所以可以设置2^32个不同的位。

之乎者也·的博客 265

Redis 数据库 入门 教程

Redis 数据库入门教程

freeking101的博客 3684

Redis知识整理一

Redis基本数据结构、高级数据结构、缓存问题等知识总结

woniu_buhui_fei的博客 402

10-Redis 进阶专题实战:Pipeline、事务、Lua、分布式锁、消息队列与特殊数据类型

本文聚焦 Redis 从“会用缓存”走向“能做系统设计”的进阶能力:Pipeline 批量通信、事务与 Lua 原子操作、分布式锁、消息队列、BitMap、HyperLogLog、布隆过滤器和 GEO。文章会按照“问题场景 -> 原理图解 -> 命令验证 -> Java/Spring 实战 -> 生产避坑”的路径讲解,帮助新手把零散知识串成可落地的技术方案。

m0_66500660的博客 319

最快速使用缓存中间件----Redis基础

新手最快入门redis的基本使用和整合

qq_55272229的博客 848

模块二:Redis 数据结构

Redis数据结构实战指南:从入门到避坑 本文通过作者亲身经历的Redis排行榜翻车案例,系统剖析了Redis五大核心数据结构的底层实现与应用场景。String采用SDS实现二进制安全存储;Hash根据数据量在ziplist和hashtable间自动切换;List通过quicklist平衡内存与性能;Set提供高效去重能力;ZSet结合跳表与字典实现排行榜功能。文章还介绍了Bitmap、HyperLogLog和布隆过滤器三种特殊结构的适用场景,以及Stream消息队列的优劣。关键教训包括:ZSet的scor

qq_37878585的博客 356
上一篇: 2018年经历过的一些事情
下一篇: 排序总结-常用排序算法Java实现
牧竹子
博客等级 码龄17年 572粉丝 233原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值