栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

redis的bitmap和geohash经纬度的使用、redis6.0的新特性

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

redis的bitmap和geohash经纬度的使用、redis6.0的新特性

Bitmap

BitMap 原本的含义是用一个比特位来映射某个元素的状态。由于一个比特位只能表示 0 和 1 两种状态,所以 BitMap 能映射的状态有限,但是使用比特位的优势是能大量的节省内存空间
可以把 Bitmap 想象成一个以比特位为单位的数组,数组的每个单元只能存储0和1,数组的下标在 Bitmap 中叫做偏移量;

注意:Redis 其实只支持 5 种数据类型,并没有 BitMap 这种类型,BitMap 底层是基于 Redis 的字符串类型实现的。
Redis 中字符串的最大长度是2^32bit= 512M,C语言中字符串的末尾都要存储一位分隔符,所以实际上 BitMap 的 offset 值上限是2^32 - 1
bitmap的相关命令:
1、设置值,其中value只能是 0 和 1
setbit key offset value
2、获取值
getbit key offset
3、获取指定范围内值为bit位为1的个数(区间统计不建议使用,bitcount用的是byte来计算位数(范围的单位是byte,两者差了8倍),其他setbit和getbit用的是bit),不加范围使用的查询所有
BITCOUNT key [start end]

3、BitMap间的运算:BITOP 支持四种表达式运算: AND(交集), OR(并集), XOR(异或) 和NOT(取非), 用法如下:
BITOP AND destkey srckey1 srckey2 srckey3 … srckeyN
BITOP OR destkey srckey1 srckey2 srckey3 … srckeyN
BITOP XOR destkey srckey1 srckey2 srckey3 … srckeyN
BITOP NOT destkey srckey
result 计算的结果,会存储在该destkey 中,not运算只能一个key

4、BITPOS key bit [start] [end]
返回设置为1或0(bit)的一个字符串中的第一个点的offset位置
bitmap的使用场景:
1、用户签到:
很多网站都提供了签到功能,并且需要展示最近一个月的签到情况,这种情况可以使用 BitMap 来实现。
命令为:setbit userId:2022 (今天是一年中的第几天) % (今年的天数) 1
2、活跃用户统计(用户登陆情况):
使用日期作为 key,然后用户 id 为 offset,如果当日活跃过就设置为1。具体怎么样才算活跃这个标准大家可以自己指定。
命令为:Setbit 2022315 userId 1
统计连续两天的活跃用户的的数量:BITOP AND destkey srckey1 srckey2
统计几天内活跃过的用户数量:BITOP OR destkey srckey1 srckey2
3、查询用户是否在线:
如果需要提供一个查询当前用户是否在线的接口,也可以考虑使用 BitMap 。即节约空间效率又高,只需要一个 key,然后用户 id 为 offset,如果在线就设置为 1,不在线就设置为 0。
命令为: setbit key userId 1;
4、实现布隆过滤器:
在布隆过滤器上不存在的是一定不存在,存在的可能不存在;
实现1:可以定义多个hash函数,定义bitmap的bit位数m,然后通过多个hash(key)%m得出多个offset,然后设置为1;
查看key是否存在,多个hash(key)%m得出多个offset,是否都为1,如果不是,则一定不存在;如果都是1,则表示可能存在。

Geohash经纬度编码:

实现原理:
经度范围是东经180到西经180,纬度范围是南纬90到北纬90,我们设定西经为负,
南纬为负,所以地球上的经度范围就是[-180, 180],纬度范围就是[-90,90]。
如果以本初子午线、赤道为界,地球可以分成4个部分;
如果纬度范围[-90°, 0°)用二进制0代表,(0°, 90°]用二进制1代表,经度范围[-180°, 0°)用二进制0代表,
(0°, 180°]用二进制1代表,那么地球可以分成如下(左图 )4个部分

通过GeoHash算法,可以将经纬度的二维坐标变成一个可排序、可比较的的字符串编码。 在编码中的每个字符代表一个区域,并且前面的字符是后面字符的父区域。其算法的过程如下:
根据GeoHash 来计算 纬度的 二进制编码
地球纬度区间是[-90,90], 如某纬度是39.92324,可以通过下面算法来进行维度编码:
1)区间[-90,90]进行二分为[-90,0),[0,90],称为左右区间,可以确定39.92324属于右区间[0,90],给标记为1
2)接着将区间[0,90]进行二分为 [0,45),[45,90],可以确定39.92324属于左区间 [0,45),给标记为0
3)递归上述过程39.92324总是属于某个区间[a,b]。随着每次迭代区间[a,b]总在缩小,并越来越逼近39.928167
4)如果给定的纬度(39.92324)属于左区间,则记录0,如果属于右区间则记录1,这样随着算法的进行会产生一个序列1011 1000 1100 0111 1001,序列的长度跟给定的区间划分次数有关。

例如11100 11101 00100 01111 00000 01101 01011 00001:
最后使用用0-9、b-z(去掉a, i, l, o)这32个字母进行base32编码,首先将11100 11101 00100 01111 00000 01101 01011 00001转成十进制 28,29,4,15,0,13,11,1,十进制对应的编码就是wx4g0ec1。同理,将编码转换成经纬度的解码算法与之相反

优点:
GeoHash利用Z阶曲线进行编码,Z阶曲线可以将二维所有点都转换成一阶曲线。地理位置坐标点通过编码转化成一维值,利用 有序数据结构如B树、SkipList等,均可进行范围搜索。因此利用GeoHash算法查找邻近点比较快
缺点:
Z 阶曲线有一个比较严重的问题,虽然有局部保序性,但是它也有突变性。在每个 Z 字母的拐角,都有可能出现顺序的突变。
命令使用:
类型为简单的zset类型
1、添加经纬度:
geoadd key longitude latitude member [longitude latitude member …] //参数为 集合名称 经度 维度 成员名称,同时一个key添加多个经纬度;
例如geoadd area 116.4159 40.0405 member1
2、获取指定地理位置的经纬度:
geopos key member [member …] //参数为 集合名称 成员名称
例如geopos area member1
3、获取两个坐标之间的距离:
geodist key member1 member2 [m km mi ft] //参数为 集合名称 成员1 成员2 距离参数 m 米 km 千米 mi 英里 ft英尺
例如geodist area member1 member2 m
4、获取指定坐标半径距离内的所有成员信息:
georadius key longitude latitude radius [m km mi ft] [WITHDIST WITHCOORD WITHHASH] [asc desc]//参数 集合名称 经度 维度 距离 [距离] [显示距离] [显示经纬度] [显示52位hash数] [正序倒序]
例如georadius area 116.4112 40.0513 2 km
5、获取指定成员半径距离内的成员信息 - 不会排除查询成员:
GEORADIUSBYMEMBER key member radius [m km mi ft] [WITHDIST WITHCOORD WITHHASH] [asc desc] //参数 集合 成员 距离 单位
例如georadiusbymember area member1 2 km

Redis6.0的新特性:
  1. 多线程
  2. Client Side Cache
  3. Acls
    1、多线程:
    1.redis 6.0 提供了多线程的支持,redis 6 以前的版本,严格来说也是多线程,只不过执行用户命令的请求时单线程模型,还有一些线程用来执行后台任务, 比如 unlink 删除 大key,rdb持久化等。

redis 6.0 提供了多线程的读写IO, 但是最终执行用户命令的线程依然是单线程的,这样,就没有多线程数据的竞争关系,依然很高效。
redis 6.0 以前线程执行模式,如下操作在一个线程中执行完成

redis 6.0 线程执行模式:
可以通过如下参数配置多线程模型
io-threads 4 // 这里说 有三个IO 线程,还有一个线程是main线程,main线程负责IO读写和命令执行操作
默认情况下,如上配置,有三个IO线程, 这三个IO线程只会执行 IO中的write 操作,也就是说,read 和 命令执行 都由main线程执行。最后多线程将数据写回到客户端

开启了如下参数:
io-threads-do-reads yes // 将支持IO线程执行 读写任务。
则会redad也是多线程:

2、client side caching
客户端缓存:redis 6 提供了服务端追踪key的变化,客户端缓存数据的特性,这需要客户端实现
执行流程为:
当客户端访问某个key时,服务端将记录key 和 client ,客户端拿到数据后,进行客户端缓存,这时,当key再次被访问时,key将被直接返回,避免了与redis 服务器的再次交互,节省服务端资源,当数据被其他请求修改时,服务端将主动通知客户端失效的key,客户端进行本地失效,下次请求时,重新获取最新数据。
目前只有lettuce对其进行了支持:

 
io.lettuce 
lettuce-core 	6.0.0.RELEASE 
 

3、3ACL 是对于命令的访问和执行权限的控制,默认情况下,可以有执行任意的指令,兼容以前版本
ACL设置有两种方式:

  1. 命令方式
    ACL SETUSER + 具体的权限规则, 通过 ACL SAVE 进行持久化
  2. 对 ACL 配置文件进行编写,并且执行 ACL LOAD 进行加载
    ACL存储有两种方式,但是两种方式不能同时配置,否则直接报错退出进程
    1.redis 配置文件: redis.conf
    2.ACL配置文件, 在redis.conf 中通过 aclfile /path 配置acl文件的路径

命令方式:
ACL SETUSER alice // 创建一个 用户名为 alice的用户
用如上的命令创建的用户语义为:

  1. 处于 off 状态, 它是被禁用的,不能用auth进行认证
  2. 不能访问任何命令
  3. 不能访问任意的key
  4. 没有密码
    如上用户alice 没有任何意义。
    创建一个对 cached: 前缀具有get命令执行权限的用户,并且设置密码:
    acl setuser alice on >pass123 ~cached:* +get
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1006511.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号