Redis新API(Bitmap,GEO)
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)相关推荐
- 03 redis新类型bitmap/hyperloglgo/GEO
亿级系统中常见的四种统计 聚合统计 统计多个集合元素的聚合结果,就是前面讲解过的交差并等集合统计 交并差集和聚合函数的应用 排序统计 抖音视频最新评论留言的场景,请你设计一个展现列表.考察你的数据结构 ...
- Redis数据实战之GEO在LBS中应用与自定义新数据类型
Redis数据实战之GEO在LBS中应用与自定义新数据类型 引言 面向 LBS 应用的 GEO 数据类型 GEO 的底层结构 GeoHash 的编码方法 如何操作 GEO 类型 如何自定义数据类型 R ...
- 六、Redis新类型bitmap-hyperloglgo-GEO
六.Redis新类型bitmap-hyperloglgo-GEO 1.统计 存的进+取得快+多统计 1.统计的类型有哪些? 1.聚合统计 统计多个集合元素的聚合结果,就是前面讲解过的交差并等集合统计 ...
- redis 用setbit(bitmap)统计活跃用户
getspool.com的重要统计数据是实时计算的.Redis的bitmap让我们可以实时的进行类似的统计,并且极其节省空间.在模拟1亿2千8百万用户的模拟环境下,在一台MacBookPro上,典型的 ...
- php版redis插件,SSDB数据库,增强型的Redis管理api实例
php版redis插件,SSDB数据库,增强型的Redis管理api实例 SSDB是一套基于LevelDB存储引擎的非关系型数据库(NOSQL),可用于取代Redis,更适合海量数据的存储. 另外,r ...
- redis 经纬度_【SpringBoot DB 系列】Redis 高级特性之 GEO
[SpringBoot DB 系列]Redis 高级特性之 GEO GEO 用于存储地理信息,最直观的就是我们日常使用的地图 app 中,如果我想查询我所在地的周边餐饮,就可以利用 geo 中的以(x ...
- Redis6发布订阅及Redis新数据类型
Redis6 Redis的发布和订阅 什么是发布和订阅 Redis的发布和订阅 发布订阅命令行实现 Redis新数据类型 Bitmaps 常用命令 1.setbit 2.实例 3. getbit 4. ...
- PyTorch 1.9发布,支持新API,可在边缘设备中执行
点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 来源丨机器之心 编辑丨极市平台 导读 PyTorch 团队发布了 P ...
- hbase建索引java api_hbase java api样例(版本1.3.1,新API)
hbase版本:1.3.1 目的:HBase新API的使用方法. 尝试并验证了如下几种java api的使用方法. 1.创建表 2.创建表(预分区) 3.单条插入 4.批量插入 5.批量插入(客户端缓 ...
最新文章
- 饿了么UI框架element的表格多个弹窗问题
- Modelsim下进行功能仿真没问题,可是在ISE综合报错,如何解决?
- 华为鸿蒙系统英语报纸_华为操作系统“鸿蒙”的英文是什么?
- python常用8大算法
- 使用 cProfile 和火焰图调优 Python 程序性能
- java map 实现 序列化,MapReduce序列化
- 禁止进入activity后EditText自动获得焦点的方法
- 家用使用计算机组装,不能再简单了!家用电脑DIY组装实操
- 轨迹规划实现 tfaar_example2.7
- CAD解决学生版的问题
- CSS+HTML开发者手册 中文参考手册合集
- ubuntu 键盘输入法为空_[已解决]HELP!!!fcitx 输入法不出来,键盘也不见了
- 台式计算机主板修理教程,小白装机最新最详细的台式电脑组装教程图解
- 记录一个找直线三等分点的方法及其证明
- 微信文章数据分析一(阅读点赞评论)
- 用html5画瀑布图,一起制作瀑布图
- 20154312 曾林 Exp4恶意软件分析
- 中国Linux发展前景怎么样?
- github搜索方法
- 华为rh2288v2服务器系统,华为RH2288H V2服务器外部简介_华为 FusionServer RH2288 V2_服务器评测与技术-中关村在线...
热门文章
- 2021-10-25 变压器零序电抗分类 总结
- 百度、华为前赴后继,固废分拣机器人“全面上道”还有多远?
- java 加密解密 工具包_java加密解密工具类
- jq获取asp:RadioButtonList中value的值
- 如何提高图表设计与制作技巧,看这一文章就够了
- 用计算机画程序框图,做项目画流程图,Word只3步搞定
- python 爬取搞笑视频_Python爬取知乎上搞笑视频,一顿爆笑送给大家
- 生命无常,请别辜负好时光!
- ASUS|华硕 天选4 FX507VV 工厂系统 带ASUS Recovery恢复功能
- 宅男冢最新链接服务器失败,宅男冢最新app