1.Bitmap 位图

1.1 Redis从2.2.0版本开始新增了setbit,getbit,bitcount等几个bitmap相关命令。虽然是新命令,但是并没有新增新的数据类型,因为setbit等命令只不过是在set上的扩展,因为redis存储String类型的数据是以二进制的形式存储,只不过bitmap是运用了二进制,不用String类型。
1.2 命令
命令 说明
setbit key offset value 设置指定键的二进制位图指定offset偏移量为value[0/1]
getbit key offset 获取指定键的二进制位图指定offset偏移量上的value
bitcount key [start] [end] 获取指定键的二进制位图所有的value为1有多少位
bitop [operation] destkey key [key …] 对指定键做运算并把结果放入destkey目标键中,operation操作有 【AND 与运算 , OR 或运算 , XOR 异或运算 , NOT 非运算】
bitfield key [operation] [u/i]offset value get是取出key对应的位图,指定value索引位开始,取offset位偏移量的二进制;
1.3 命令demo演示
  • setbit key offset value
    设置指定key的offset位上的bit值为value,value只能是1或0,返回在offset处原来的bit值
setbit lzj 0 1   #返回值 0

  • getbit key offset
    获取offset处的bit值
getbit lzj 0  #返回值 1
  • bitcount key [start] [end]
    获取开始索引 到 结束索引 之间bit值为1 的数量
bitcount lzj 0 -1 #返回值 1
  • bitop [operation] destkey key [key …]
    把指定的多个键的二进制进行计算操作,并把计算后的二进制放入指定键中,返回结果放入键中字符串长度,最多只能处理64个连续的位。
setbit lzj1 0 1
bitop and result lzj lzj1  #返回值1
  • bitfield key [operation] [u/i]offset value
    get是取出key对应的位图,指定value索引位开始,取offset位偏移量的二进制;
bitfield result get u8 0  #返回128
bitfield result get i8 0  #返回-128
#其他 还没有弄懂

1.4 下面可以用java代码通过redistemplate去获取一个字符串的二进制位图
@SpringBootTest(classes = RedissiondemoApplication.class)
class ShopServiceImplTest {@Autowiredprivate RedisTemplate<String,String> redisTemplate;@Testvoid consumer() {redisTemplate.opsForValue().set("lzj","jj");String res = redisTemplate.opsForValue().get("lzj");//输出一个String类型的bitmap位图System.out.println(toBinary(res.getBytes()));//输出十进制数组System.out.println(Arrays.toString(res.getBytes()));}public static String toBinary(byte[] bytes){//把字符串转成字符数组StringBuilder result= new StringBuilder();for(int i=0;i<bytes.length;i++){//byte是8位的,而int是32位,直接转换会在前面补24个1,所以 & 0xFF 消除掉StringBuilder binary= new StringBuilder(Integer.toBinaryString(bytes[i] & 0xFF));int len=8-binary.length();if(len>0){//不足8位补够for(int j=0;j<len;j++){binary.insert(0,"0");}}result.append(binary).append(" ");}return result.toString();}
}

可以看到从右到左是从低位到高位,二进制(8bit)转化为 十进制数组。
1.5 Bitmap怎么使用,根据二进制形式 是0 1 组成,所以我们可以用来做为一个用户的签到,用户签到就是1,没有签到就是 0(因为限制大小时512M就是2^32-1位),下面我将实现一个简单的demo。
1.6
@SpringBootTest(classes = RedissiondemoApplication.class)
public class Demo1 {@Autowiredprivate RedisTemplate<String,String> redisTemplate;/*** 用户签到** @param uid  用户ID* @param date 日期* @return 之前的签到状态*/public boolean doSign(int uid, LocalDate date) {int offset = date.getDayOfMonth() - 1;return redisTemplate.opsForValue().setBit(buildSignKey(uid, date), offset, true);}/*** 检查用户是否签到** @param uid  用户ID* @param date 日期* @return 当前的签到状态*/public boolean checkSign(int uid, LocalDate date) {int offset = date.getDayOfMonth() - 1;return redisTemplate.opsForValue().getBit(buildSignKey(uid, date), offset);}/*** 获取用户签到次数** @param uid  用户ID* @param date 日期* @return 当前的签到次数*/public long getSignCount(int uid, LocalDate date) {return redisTemplate.execute((RedisCallback<Long>) con -> con.bitCount(buildSignKey(uid, date).getBytes()));}public static String toBinary(byte[] bytes){//把字符串转成字符数组StringBuilder result= new StringBuilder();for(int i=0;i<bytes.length;i++){//byte是8位的,而int是32位,直接转换会在前面补24个1,所以 & 0xFF 消除掉StringBuilder binary= new StringBuilder(Integer.toBinaryString(bytes[i] & 0xFF));int len=8-binary.length();if(len>0){//不足8位补够for(int j=0;j<len;j++){binary.insert(0,"0");}}result.append(binary).append(" ");}return result.toString();}/*** 获取当月连续签到次数** @param uid  用户ID* @param date 日期* @return 当月连续签到次数*/public long getContinuousSignCount(int uid, LocalDate date) {int signCount = 0;System.out.println(date.getDayOfMonth());//命令: bitfield key get [u/i]offset value 此命令就是get取出key对应的位图,指定value索引位开始,取offset位偏移量的二进制BitFieldSubCommands bitFieldSubCommands = BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(date.getDayOfMonth())).valueAt(0);List<Long> list = redisTemplate.opsForValue().bitField(buildSignKey(uid, date),bitFieldSubCommands);if (list != null && list.size() > 0) {// 取低位连续不为0的个数即为连续签到次数,需考虑当天尚未签到的情况long v = list.get(0) == null ? 0 : list.get(0);for (int i = 0; i < date.getDayOfMonth(); i++) {//因为取的是无符号的二进制,所以右移一位,左移一位,依然相等只有是最右边是0[没签到]的时候,if (v >> 1 << 1 == v) {// 只有除了第一天以外没签到,才算断签。if (i > 0) break;} else {// 签到了 签到数加1signCount += 1;}//右移一位并赋值,相当于把最左边一位去除v >>= 1;}}return signCount;}/*** 获取当月首次签到日期** @param uid  用户ID* @param date 日期* @return 首次签到日期*/public LocalDate getFirstSignDate(int uid, LocalDate date) {Long pos = redisTemplate.execute((RedisCallback<Long>) con -> con.bitPos(buildSignKey(uid, date).getBytes(), true));return pos < 0 ? null : date.withDayOfMonth((int) (pos + 1));}/*** 获取当月连续签到次数** @param uid  用户ID* @param date 日期* @return 当月连续签到次数*/public long getContinuousSignCount(int uid, LocalDate date) {int signCount = 0;System.out.println(date.getDayOfMonth());//命令: bitfield key get [u/i]offset value BitFieldSubCommands bitFieldSubCommands = BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(date.getDayOfMonth())).valueAt(0);List<Long> list = redisTemplate.opsForValue().bitField(buildSignKey(uid, date),bitFieldSubCommands);if (list != null && list.size() > 0) {// 取低位连续不为0的个数即为连续签到次数,需考虑当天尚未签到的情况long v = list.get(0) == null ? 0 : list.get(0);for (int i = 0; i < date.getDayOfMonth(); i++) {//因为取的是无符号的二进制,所以右移一位,左移一位,依然相等只有是最右边是0[没签到]的时候,if (v >> 1 << 1 == v) {// 只有除了第一天以外没签到,才算断签。if (i > 0) break;} else {// 签到了 签到数加1signCount += 1;}//右移一位并赋值,相当于把最左边一位去除v >>= 1;}}return signCount;}private static String formatDate(LocalDate date) {return formatDate(date, "yyyyMM");}private static String formatDate(LocalDate date, String pattern) {return date.format(DateTimeFormatter.ofPattern(pattern));}private static String buildSignKey(int uid, LocalDate date) {return String.format("u:sign:%d:%s", uid, formatDate(date));}private Integer ID = 2017131132;/*** 当天签到*/@Testvoid sign() {LocalDate today = LocalDate.now().minusDays(1);String todayDate = formatDate(today,"yyyyMMdd");System.out.println(doSign(ID, today)==true?"已签到【" + todayDate + "】":"签到成功【" + todayDate + "】");}/*** 检查当天是否签到*/@Testvoid checkSign(){LocalDate today = LocalDate.now().minusDays(1);String todayDate = formatDate(today,"yyyyMMdd");System.out.println(checkSign(ID,today)==true?"【" + todayDate + "】已签到":"【" + todayDate + "】未签到");}/*** 获取今月 签到次数*/@Testvoid getSignCount(){LocalDate today = LocalDate.now();long signCount = getSignCount(ID, today);System.out.println(today.getMonth().getValue() + "月份签到了" + signCount + "次");}/*** 获取连续签到次数* 注意: 如果当天没有签到是不算做断签,因为当天可以签到,如果前天没有签到就是断签了,不属于连续签到计算范围*/@Testvoid getContinuousSignCount(){LocalDate today = LocalDate.now();long continuousSignCount = getContinuousSignCount(ID, today);System.out.println("连续签到" + continuousSignCount + "天");}/*** 获取第一天签到*/@Testvoid getFirstSignDate(){LocalDate today = LocalDate.now();LocalDate firstSignDate = getFirstSignDate(ID, today);System.out.println("首次签到日期是" + formatDate(firstSignDate,"yyyyMMdd"));}/*** 获取用户的签到信息*/@Testvoid getSignInfo(){LocalDate today = LocalDate.now();getSignInfo(ID, today).forEach((k,v) -> {System.out.println(k + "  : " + (v ?"√":"×"));});}}

2.GEO

redis 3.2版本以上 才能使用的API
API 作用
GEOADD key longitude latitude member 用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中
GEOPOS key member [member …] 用于从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil。
GEODIST key member1 member2 [m/km/ft/mi] 用于返回两个给定位置之间的距离。
GEORADIUS key longitude latitude radius [m/km/ft/mi] 获取以指定坐标内半径为raduis的圆内的元素个数
GEORADIUSBYMEMBER key member radius [m/km/ft/mi] 获取以指定键的成员的内半径为raduis的圆内的元素个数
GEOHASH key member [member …] geohash 来保存地理位置的坐标。
  • GEOADD key longitude latitude member
    用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中
geoadd lzj 113.762141 22.978418 "广东科技学院"
geoadd lzj 113.769143 22.933629 "水濂山森林公园"
  • GEOPOS key member [member …]
    用于从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil。
geopos lzj "广东科技学院"
geopos lzj "水濂山森林公园"
  • GEODIST key member1 member2 [m/km/ft/mi]
    用于返回两个给定位置之间的距离。
geodist lzj "广东科技学院" "水濂山森林公园" km
  • GEORADIUS key longitude latitude radius [m/km/ft/mi]
    和GEODIST作用一样,但是 georadiusbymember 的中心点是由给定的位置元素决定的, 而不是使用经度和纬度来决定中心点。
    – WITHDIST : 返回距离
    – WITHCOORD : 返回经纬度
    – WITHHASH : 返回geohash值
    – [ASC/DESC] : 规定距离排序顺序
    – COUNT : 返回的指定记录数
georadius lzj 113 22 5 km
  • GEORADIUSBYMEMBER key member radius [m/km/ft/mi]
    获取以指定键的成员的内半径为raduis的圆内的元素个数
    – WITHDIST : 返回距离
    – WITHCOORD : 返回经纬度
    – WITHHASH : 返回geohash值
    – [ASC/DESC] : 规定距离排序顺序
    – COUNT : 返回的指定记录数
georadiusbymember lzj "广东科技学院" 7 km
  • GEOHASH key member [member …]
    geohash 来保存地理位置的坐标
geohash lzj "广东科技学院"

一键查询淘宝/拼多多内部优惠券,每日大额外卖红包,购物省钱的宝藏工具

Redis新API(Bitmap,GEO)相关推荐

  1. 03 redis新类型bitmap/hyperloglgo/GEO

    亿级系统中常见的四种统计 聚合统计 统计多个集合元素的聚合结果,就是前面讲解过的交差并等集合统计 交并差集和聚合函数的应用 排序统计 抖音视频最新评论留言的场景,请你设计一个展现列表.考察你的数据结构 ...

  2. Redis数据实战之GEO在LBS中应用与自定义新数据类型

    Redis数据实战之GEO在LBS中应用与自定义新数据类型 引言 面向 LBS 应用的 GEO 数据类型 GEO 的底层结构 GeoHash 的编码方法 如何操作 GEO 类型 如何自定义数据类型 R ...

  3. 六、Redis新类型bitmap-hyperloglgo-GEO

    六.Redis新类型bitmap-hyperloglgo-GEO 1.统计 存的进+取得快+多统计 1.统计的类型有哪些? 1.聚合统计 统计多个集合元素的聚合结果,就是前面讲解过的交差并等集合统计 ...

  4. redis 用setbit(bitmap)统计活跃用户

    getspool.com的重要统计数据是实时计算的.Redis的bitmap让我们可以实时的进行类似的统计,并且极其节省空间.在模拟1亿2千8百万用户的模拟环境下,在一台MacBookPro上,典型的 ...

  5. php版redis插件,SSDB数据库,增强型的Redis管理api实例

    php版redis插件,SSDB数据库,增强型的Redis管理api实例 SSDB是一套基于LevelDB存储引擎的非关系型数据库(NOSQL),可用于取代Redis,更适合海量数据的存储. 另外,r ...

  6. redis 经纬度_【SpringBoot DB 系列】Redis 高级特性之 GEO

    [SpringBoot DB 系列]Redis 高级特性之 GEO GEO 用于存储地理信息,最直观的就是我们日常使用的地图 app 中,如果我想查询我所在地的周边餐饮,就可以利用 geo 中的以(x ...

  7. Redis6发布订阅及Redis新数据类型

    Redis6 Redis的发布和订阅 什么是发布和订阅 Redis的发布和订阅 发布订阅命令行实现 Redis新数据类型 Bitmaps 常用命令 1.setbit 2.实例 3. getbit 4. ...

  8. PyTorch 1.9发布,支持新API,可在边缘设备中执行

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 来源丨机器之心 编辑丨极市平台 导读 PyTorch 团队发布了 P ...

  9. hbase建索引java api_hbase java api样例(版本1.3.1,新API)

    hbase版本:1.3.1 目的:HBase新API的使用方法. 尝试并验证了如下几种java api的使用方法. 1.创建表 2.创建表(预分区) 3.单条插入 4.批量插入 5.批量插入(客户端缓 ...

最新文章

  1. 确认!语音识别大牛Daniel Povey将入职小米,曾遭霍普金斯大学解雇,怒拒Facebook
  2. 2009年8月26日,用于win2003上的MSN不能正常使用
  3. 解决Ubuntu与Windows之间无法复制粘贴问题
  4. 苹果决定不修复 Big Sur 和 Catalina 中的这两个0day
  5. Windows Mobile Sensors API库的设计
  6. Kubernetes 小白学习笔记(4)--kubernetes是什么
  7. 理解SNS系列之二:更进一步,近观SNS
  8. Gliffy Diagrams 好用的流程图工具
  9. 打蚊子表情包_打死蚊子表情包 - 打死蚊子微信表情包 - 打死蚊子QQ表情包 - 发表情 fabiaoqing.com...
  10. 与美不期而遇:Carry on Till Tomorrow
  11. 有道云笔记markdown字体增大、生成目录
  12. 国内可用的 ChatGPT
  13. mstsc连接传输大文件时突然中断
  14. 第一课 request传参
  15. IIS配置反向代理URL rewrite.dll加载失败
  16. 开发规范及具体开发任务分工
  17. 玻璃幕墙清洗机器人市场前景_玻璃幕墙越障清洁机器人
  18. gdb调试程序时跳进函数和跳出函数
  19. 用c语言实现cos x 函数
  20. CASIA-OLHWDB2.0-2.2数据集wptt文件解析

热门文章

  1. AEG-12A-02-D2-2-50,AEG-12A-02-D2-C-50比例阀控制器
  2. AMD负责YES,英特尔负责赚钱
  3. 大砍广告投放,还威胁要下架Twitter,马斯克怒向苹果开炮:宁可开战也不付30%“过路费”
  4. AIBlockChain:“知名博主独家讲授”人工智能创新应用竞赛【精选实战作品】之《基于计算机视觉、自然语言处理、区块链和爬虫技术的智能会议系统》软件系统案例的界面简介、功能介绍分享之总篇
  5. 怎么给电话手表安上Android,电话手表安卓版
  6. 在win10中开启64位ie浏览器的方法(IE11)
  7. 中职计算机vb听课记录,中职学校《VB语言程序设计》教学浅析
  8. 计算机专业的职业树,计算机专业职业生涯规划
  9. 淘宝,tmall,1688,抖音,拼多多等平台商品详情接口(网络爬虫数据接口调用示例)接口对接教程
  10. 手机android的文件怎么恢复,如何恢复安卓手机内置存储中已删除的文件