前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis点赞新思路 bitmap

Redis点赞新思路 bitmap

作者头像
疯狂的KK
发布2020-09-23 10:40:09
1.4K1
发布2020-09-23 10:40:09
举报
文章被收录于专栏:Java项目实战Java项目实战

1.使用场景

用户上线次数统计、统计活跃用户,签到,点赞等具有标识性功能

2.原理

就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身,是bit不是byte,1byte=8bit,优点凸显,就是贼鸡儿省空间

空间占用、以及第一次分配空间需要的时间

在一台2010MacBook Pro上,offset为2^32-1(分配512MB)需要~300ms,offset为2^30-1(分配128MB)需要~80ms,offset为2^28-1(分配32MB)需要~30ms,offset为2^26-1(分配8MB)需要8ms。<来自官方文档>

大概的空间占用计算公式是:($offset/8/1024/1024)MB)

说起来bitmap不能算为一种新数据类型,只是set的扩展

3.命令

命令

作用

setbit

设置Bitmap的值

getbit

获取Bitmap的值

bitcount

获取指定范围内值为1的个数

destkey

对Bitmap做操作,可以是and(交集),or(并集),not(非集)或者xor(异或)

BITOP

BITOP operation destkey key [key ...],operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种:● BITOP AND destkey key [key ...] ,对一个或多个 key 求逻辑并,并将结果保存到 destkey 。● BITOP OR destkey key [key ...] ,对一个或多个 key 求逻辑或,并将结果保存到 destkey 。● BITOP XOR destkey key [key ...] ,对一个或多个 key 求逻辑异或,并将结果保存到 destkey 。● BITOP NOT destkey key ,对给定 key 求逻辑非,并将结果保存到 destkey 。除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入

BITPOS

BITPOS key bit [start][end]返回字符串里面第一个被设置为 1 或者 0 的bit位。

BITFIELD

BITFIELD key [GET type offset][SET type offset value][INCRBY type offset increment][OVERFLOW WRAP|SAT|FAIL]

溢出控制

用户可以通过 OVERFLOW 命令以及以下展示的三个参数, 指定 BITFIELD 命令在执行自增或者自减操作时, 碰上向上溢出(overflow)或者向下溢出(underflow)情况时的行为:

  • WRAP :使用回绕(wrap around)方法处理有符号整数和无符号整数的溢出情况。对于无符号整数来说, 回绕就像使用数值本身与能够被储存的最大无符号整数执行取模计算, 这也是 C 语言的标准行为。对于有符号整数来说, 上溢将导致数字重新从最小的负数开始计算, 而下溢将导致数字重新从最大的正数开始计算。比如说, 如果我们对一个值为 127 的 i8 整数执行加一操作, 那么将得到结果 -128 。
  • SAT :使用饱和计算(saturation arithmetic)方法处理溢出, 也即是说, 下溢计算的结果为最小的整数值, 而上溢计算的结果为最大的整数值。举个例子, 如果我们对一个值为 120 的 i8 整数执行加 10 计算, 那么命令的结果将为 i8 类型所能储存的最大整数值 127 。与此相反, 如果一个针对 i8 值的计算造成了下溢, 那么这个 i8 值将被设置为 -127 。
  • FAIL :在这一模式下, 命令将拒绝执行那些会导致上溢或者下溢情况出现的计算, 并向用户返回空值表示计算未被执行。

需要注意的是, OVERFLOW 子命令只会对紧随着它之后被执行的 INCRBY 命令产生效果, 这一效果将一直持续到与它一同被执行的下一个 OVERFLOW 命令为止。在默认情况下, INCRBY 命令使用 WRAP 方式来处理溢出计算。

4.优点

省空间

5.缺点

暂无,虽然一个标识位只能记录一个用户,那也够用了毕竟你没有2^32-1的数据量

6.实现场景点赞

新增redis方法setbit

代码语言:javascript
复制
//bitmap
/**
 * Sets the bit at {@code offset} in value stored at {@code key}.
 *
 * @param key must not be {@literal null}.
 * @param offset
 * @param value
 * @since 1.5
 * @see <a href="http://redis.io/commands/setbit">Redis Documentation: SETBIT</a>
 */
Boolean setBit(K key, long offset, boolean value);
/*
* setbit
* */
public Boolean setBitMap(String key,long commentDatailId,boolean value){
return  redisTemplate.opsForValue().setBit(key,commentDatailId,value);
}

在命令中value是标识1或0的,也就是true/false对应值

key:设置的key,比如日活,签到,就用时间+id,那标识点赞未点赞就用信息id即可

offset:即所占标识位,一看就想起来偏移量

value:设置0/1

Boolean :返回0或1来标识是否

代码语言:javascript
复制
boolean flag = redisService.setBitMap(userIdStr,commentDetailId,true);

以前的逻辑不变set之前判断是否存在

代码语言:javascript
复制
if(redisService.getBitMap(userIdStr,commentDetailId)){
    redisService.setBitMap(userIdStr,commentDetailId,true);
}else{
    redisService.setBitMap(userIdStr,commentDetailId,false);
}

问题:如果我的id很大或者是uuid开始呢?

正常的id是不会的,但uuid有可能,如果是uuid可以使用uuid减去初始位来进行放置

实现场景大数据量黑名单

此业务适合大数据量业务存储的占用空间问题,而且基于redis速度不用担心

日活统计

代码语言:javascript
复制
bitop and time moday thurday

1.节约空间,统计一亿人每天的登录情况,用一亿bit,约1200WByte,约10M的字符就能表示(因为bitop命令的返回值是保存到 time中的字符串的长度(以字节byte为单位),和输入 key 中最长的字符串长度相等。即1亿除以8bit=1250万Byte);

2.计算方便

性能:

  如果你的 bitmap 数据非常大,那么可以考虑使用以下两种方法:

● 将一个大的 bitmap 分散到不同的 key 中,作为小的 bitmap 来处理。使用 Lua 脚本可以很方便地完成这一工作。

● 使用 BITCOUNT 的 start 和 end 参数,每次只对所需的部分位进行计算,将位的累积工作(accumulating)放到客户端进行,并且对结果进行缓存 (caching)。

何时使用:

  如果活跃用户在百万级别,使用Redis BitMap很划算。

  如果活跃用户很少,而用户id都是10位以上的int。那就很浪费内存了,还不如使用set集合,然后求交集就可以了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 赵KK日常技术记录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档