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. 饿了么UI框架element的表格多个弹窗问题
  2. Modelsim下进行功能仿真没问题,可是在ISE综合报错,如何解决?
  3. 华为鸿蒙系统英语报纸_华为操作系统“鸿蒙”的英文是什么?
  4. python常用8大算法
  5. 使用 cProfile 和火焰图调优 Python 程序性能
  6. java map 实现 序列化,MapReduce序列化
  7. 禁止进入activity后EditText自动获得焦点的方法
  8. 家用使用计算机组装,不能再简单了!家用电脑DIY组装实操
  9. 轨迹规划实现 tfaar_example2.7
  10. CAD解决学生版的问题
  11. CSS+HTML开发者手册 中文参考手册合集
  12. ubuntu 键盘输入法为空_[已解决]HELP!!!fcitx 输入法不出来,键盘也不见了
  13. 台式计算机主板修理教程,小白装机最新最详细的台式电脑组装教程图解
  14. 记录一个找直线三等分点的方法及其证明
  15. 微信文章数据分析一(阅读点赞评论)
  16. 用html5画瀑布图,一起制作瀑布图
  17. 20154312 曾林 Exp4恶意软件分析
  18. 中国Linux发展前景怎么样?
  19. github搜索方法
  20. 华为rh2288v2服务器系统,华为RH2288H V2服务器外部简介_华为 FusionServer RH2288 V2_服务器评测与技术-中关村在线...

热门文章

  1. 2021-10-25 变压器零序电抗分类 总结
  2. 百度、华为前赴后继,固废分拣机器人“全面上道”还有多远?
  3. java 加密解密 工具包_java加密解密工具类
  4. jq获取asp:RadioButtonList中value的值
  5. 如何提高图表设计与制作技巧,看这一文章就够了
  6. 用计算机画程序框图,做项目画流程图,Word只3步搞定
  7. python 爬取搞笑视频_Python爬取知乎上搞笑视频,一顿爆笑送给大家
  8. 生命无常,请别辜负好时光!
  9. ASUS|华硕 天选4 FX507VV 工厂系统 带ASUS Recovery恢复功能
  10. 宅男冢最新链接服务器失败,宅男冢最新app