redis统计⽤户⽇活量_「SpringBoot系列」Redis位图使⽤姿势
及应⽤场景
【SpringBoot DB 系列】Redis ⾼级特性之 Bitmap 使⽤姿势及应⽤场景介绍
前⾯介绍过 redis 的五种基本数据结构,如 String,List, Set, ZSet, Hash,这些属于相对常见了;在这些基本结果之上,redis 还提供了
⼀些更⾼级的功能,如 geo, bitmap, hyperloglog,pub/sub,本⽂将主要介绍 Bitmap 的使⽤姿势以及其适⽤场景,主要知识点包括bitmap 基本使⽤
⽇活统计应⽤场景中 bitmap 使⽤姿势
点赞去重应⽤场景中 bitmap 使⽤姿势
布隆过滤器 bloomfilter 基本原理及体验 case
I. 基本使⽤
1. 配置
我们使⽤ SpringBoot 2.2.1.RELEASE来搭建项⽬环境,直接在l中添加 redis 依赖
org.springframework.boot    spring-boot-starter-data-redis
如果我们的 redis 是默认配置,则可以不额外添加任何配置;也可以直接在l配置中,如下
spring:  redis:    host: 127.0.0.1    port: 6379    password:
2. 使⽤姿势
bitmap 主要就三个操作命令,setbit,getbit以及 bitcount
a. 设置标记
即setbit,主要是指将某个索引,设置为 1(设置 0 表⽰抹去标记),基本语法如下
# 请注意这个index必须是数字,后⾯的value必须是0/1setbit key index 0/1
对应的 SpringBoot 中,借助 RestTemplate 可以⽐较容易的实现,通常有两种写法,都可以
@Autowiredprivate StringRedisTemplate redisTemplate;/** * 设置标记位 * * @param key * @param offset * @param tag * @return */public Boolean mark(String ke
上⾯两种写法的核⼼区别,就是 key 的序列化问题,第⼀种写法使⽤默认的 jdk 字符串序列化,和后⾯的getBytes()会有⼀些区别,关于
这个,有兴趣的⼩伙伴可以看⼀下我之前的博⽂: RedisTemplate 配置与使⽤#序列化问题
b. 判断存在与否
即 getbit key index,如果返回 1,表⽰存在否则不存在
/** * 判断是否标记过 * * @param key * @param offest * @return */public Boolean container(String ke
y, long offest) {    return redisTemplate.opsForValue().getBit(k
c. 计数
即 bitcount key,统计和
/** * 统计计数 * * @param key * @return */public long bitCount(String key) {    ute(new RedisCallback() {        @Override        public Long
3. 应⽤场景
前⾯的基本使⽤⽐较简单,在介绍 String 数据结构的时候也提过,我们重点需要关注的是 bitmap 的使⽤场景,它可以⼲嘛⽤,什么场景
下使⽤它会有显著的优势
⽇活统计
点赞
bloomfilter
上⾯三个场景虽有相似之处,但实际的应⽤场景还是些许区别,接下来我们逐⼀进⾏说明
a. ⽇活统计
统计应⽤或⽹站的⽇活,这个属于⽐较常见的 case 了,如果是⽤ redis 来做这个事情,⾸先我们最容易想到的是 Hash 结构,⼀般逻辑如
根据⽇期,设置 key,如今天为 2020/10/13, 那么 key 可以为 app_20_10_13
其次当⽤户访问时,设置 field 为 userId, value 设置为 true
判断⽇活则是统计 map 的个数hlen app_20_10_13
上⾯这个逻辑有⽑病么?当然没有问题,但是想⼀想,当我们的应⽤做的很 nb 的时候,每天的⽇活都是百万,千万级时,这个内存开销就
有点吓⼈了
接下来我们看⼀下 bitmap 可以怎么做
同样根据⽇期设置 key
当⽤户访问时,index 设置为 userId,setbit app_20_10_13 uesrId 1
⽇活统计 bitcount app_20_10_13
简单对⽐⼀下上⾯两种⽅案
当数据量⼩时,且 userid 分布不均匀,⼩的为个位数,⼤的⼏千万,上亿这种,使⽤ bitmap 就有点亏了,因为 userId 作为 index,那
么 bitmap 的长度就需要能容纳最⼤的 userId,但是实际⽇活⼜很⼩,说明 bitmap 中间有⼤量的空⽩数据
反之当数据量很⼤时,⽐如百万/千万,userId 是连续递增的场景下,bitmap 的优势有两点:1.存储开销⼩, 2.统计总数快
c. 点赞
点赞的业务,最主要的⼀点是⼀个⽤户点赞过之后,就不能继续点赞了(当然某些业务场景除外),所以我们需要知道是否可以继续点赞
上⾯这个 hash 当然也可以实现,我们这⾥则主要讨论⼀下 bitmap 的实现逻辑
⽐如我们希望对⼀个⽂章进⾏点赞统计,那么我们根据⽂章 articleId 来⽣成 redisKey=like_1121,将 userId 作为 index
⾸先是通过getbit like_1121 userId 来判断是否点赞过,从⽽限制⽤户是否可以操作
Hash 以及 bitmap 的选择和上⾯的考量范围差不多
d. 布隆过滤器 bloomfilter
布隆过滤器可谓是⼤名⿍⿍了,我们这⾥简单的介绍⼀下这东西是啥玩意
底层存储为⼀个 bitmap
当来⼀个数据时,经过 n 个 hash 函数,得到 n 个数值
将 hash 得到的 n 个数值,映射到 bitmap,标记对应的位置为 1
如果来⼀个数据,通过 hash 计算之后,若这个 n 个值,对应的 bitmap 都是 1,那么表⽰这个数据可能存在;如果有⼀个不为 1,则表⽰
这个数据⼀定不存在
请注意:不存在时,是⼀定不存在;存在时,则不⼀定
从上⾯的描述也知道,bloomfilter 的底层数据结构就是 bitmap,当然它的关键点在 hash 算法;根据它未命中时⼀定不存在的特性,⾮
常适⽤于缓存击穿的问题解决
体验说明
# docker ⽅式安装docker run -p 6379:6379 --name redis-redisbloom redislabs/rebloom:latest# 通过redis-cli⽅式访问docker exec -it redis-redisbloom bash# 开始使
bloomfilter 的使⽤⽐较简单,主要是两个命令bf.add添加元素,bf.exists判断是否存在,请注意它没有删除哦
4. ⼩结
bitmap 位图属于⼀个⽐较精巧的数据结构,通常在数据量⼤的场景下,会有出现的表现效果;redis 本⾝基于 String 数据结构来实现
bitmap 的功能⽀持,使⽤⽅式⽐较简单,基本上就下⾯三个命令
setbit key index 1/0: 设置
getbit key index: 判断是否存在
bitcount key: 计数统计
本⽂也给出了 bitmap 的三个常见的应⽤场景
⽇活统计:主要借助bitcount来获取总数(后⾯会介绍,在⽇活⼗万百万以上时,使⽤ hyperLogLog 更优雅)
点赞: 主要借助setbit/getbit来判断⽤户是否赞过,从⽽实现去重
bloomfilter: 基于 bitmap 实现的布隆过滤器,⼴泛⽤于去重的业务场景中(如缓存穿透,爬⾍ url 去重等)
总的来讲,bitmap 属于易⽤,巧⽤的数据结构,⽤得好即能节省内存也可以提⾼效率,⽤得不好貌似也不会带来太⼤的问题
II. 其他
0. 项⽬
系列博⽂
【DB 系列】Redis 之管道 Pipelined 使⽤姿势
【DB 系列】Redis 集环境配置
【DB 系列】借助 Redis 搭建⼀个简单站点统计服务(应⽤篇)
【DB 系列】借助 Redis 实现排⾏榜功能(应⽤篇)
【DB 系列】Redis 之 ZSet 数据结构使⽤姿势
【DB 系列】Redis 之 Set 数据结构使⽤姿势
springboot推荐算法
【DB 系列】Redis 之 Hash 数据结构使⽤姿势
【DB 系列】Redis 之 List 数据结构使⽤姿势
【DB 系列】Redis 之 String 数据结构的读写
【DB 系列】Redis 之 Jedis 配置
【DB 系列】Redis 之基本配置
⼯程源码
⼯程:github/liuyueyi/spring-boot-demo
项⽬源码: github/liuyueyi/spring-boot-demo/tree/master/spring-boot/122-redis-template
1. ⼀灰灰 Blog
尽信书则不如,以上内容,纯属⼀家之⾔,因个⼈能⼒有限,难免有疏漏和错误之处,如发现 bug 或者有更好的建议,欢迎批评指正,不吝感激
下⾯⼀灰灰的个⼈博客,记录所有学习和⼯作中的博⽂,欢迎⼤家前去逛逛
⼀灰灰 Blog 个⼈博客 p
⼀灰灰 Blog-Spring 专题博客 p

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。