Redis 版本 6.0+
1. Geospatial地理位置
朋友的定位,附近的人,打车距离计算?
Redis的Geospatial在Redis的3.2版本推出。这个功能可以推算出地理位置信息,两地之间的距离,方圆几里的人!
使用工具:经纬度在线查询
只有6个命令:
- geoadd
添加地理位置:
规则:南北两极无法添加,用此功能,一般会下载城市数据,直接通过java程序一次性导入!
#geoadd key 经度 纬度 名称
#有效的经度:-180到180
#有效的维度:-85.05112878到85.05112878
127.0.0.1:6379> geoadd China:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> geoadd China:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd China:city 106.50 29.53 chongqing
(integer) 1
127.0.0.1:6379> geoadd China:city 114.05 22.52 shenzhen
(integer) 1
127.0.0.1:6379> geoadd China:city 120.16 30.24 hangzhou 108.96 34.26 xian
(integer) 2
- geopos
获得当前定位,一定是一个坐标值。
获取指定城市的经度和纬度
127.0.0.1:6379> geopos China:city beijing
1) 1) "116.39999896287918091"
2) "39.90000009167092543"
127.0.0.1:6379> geopos China:city beijing shanghai
1) 1) "116.39999896287918091"
2) "39.90000009167092543"
2) 1) "121.47000163793563843"
2) "31.22999903975783553"
- geodist
返回两个给定位置之间的距离(直线距离)。
如果两个位置之间的其中一个不存在, 那么命令返回空值。
指定单位的参数 unit 必须是以下单位的其中一个:
- m 表示单位为米。
- km 表示单位为千米。
- mi 表示单位为英里。
- ft 表示单位为英尺。
如果用户没有显式地指定单位参数, 那么 GEODIST
默认使用米作为单位。
GEODIST
命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差
#GEODIST key member1 member2
127.0.0.1:6379> geodist China:city beijing chongqing
"1464070.8051"
127.0.0.1:6379> geodist China:city beijing chongqing km
"1464.0708"
- georadius
以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
范围可以使用以下其中一个单位:
- m 表示单位为米。
- km 表示单位为千米。
- mi 表示单位为英里。
- ft 表示单位为英尺。
在给定以下可选项时, 命令会返回额外的信息:
WITHDIST
: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。WITHCOORD
: 将位置元素的经度和维度也一并返回。WITHHASH
: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
命令默认返回未排序的位置元素。 通过以下两个参数, 用户可以指定被返回位置元素的排序方式:
ASC
: 根据中心的位置, 按照从近到远的方式返回位置元素。DESC
: 根据中心的位置, 按照从远到近的方式返回位置元素。
在默认情况下, GEORADIUS 命令会返回所有匹配的位置元素。 虽然用户可以使用 COUNT <count>
选项去获取前 N 个匹配元素, 但是因为命令在内部可能会需要对所有被匹配的元素进行处理, 所以在对一个非常大的区域进行搜索时, 即使只使用 COUNT
选项去获取少量元素, 命令的执行速度也可能会非常慢。 但是从另一方面来说, 使用 COUNT
选项去减少需要返回的元素数量, 对于减少带宽来说仍然是非常有用的。
# georadius
127.0.0.1:6379> georadius China:city 110 30 100 km #寻找经度110、纬度30的半径100km内的城市
(empty list or set)
127.0.0.1:6379> georadius China:city 110 30 500 km #寻找经度110、纬度30的半径500km内的城市
1) "chongqing"
2) "xian"
127.0.0.1:6379> georadius China:city 110 30 500 km withcoord #寻找经度110、纬度30的半径100km内的城市 结果显示经纬度
1) 1) "chongqing"
2) 1) "106.49999767541885376"
2) "29.52999957900659211"
2) 1) "xian"
2) 1) "108.96000176668167114"
2) "34.25999964418929977"
127.0.0.1:6379> georadius China:city 110 30 500 km withcoord count 1 #寻找经度110、纬度30的半径100km内的城市 结果显示经纬度 结果只要1项
1) 1) "chongqing"
2) 1) "106.49999767541885376"
2) "29.52999957900659211"
- georadiusbymember
这个命令和 GEORADIUS命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER
的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点
指定成员的位置被用作查询的中心。
127.0.0.1:6379> georadiusbymember China:city beijing 1000 km
1) "beijing"
2) "xian"
127.0.0.1:6379> georadiusbymember China:city shanghai 400 km
1) "hangzhou"
2) "shanghai"
- geohash
返回一个或多个位置元素的 Geohash 表示。
通常使用表示位置的元素使用不同的技术,使用Geohash位置52点整数编码。由于编码和解码过程中所使用的初始最小和最大坐标不同,编码的编码也不同于标准。此命令返回一个标准的Geohash,在维基百科和geohash.org网站都有相关描述
# 将二维的经纬度转为一维的字符串 如果两个城市越近,那么距离就越进
127.0.0.1:6379> geohash China:city beijing shanghai
1) "wx4fbxxfke0"
2) "wtw3sj5zbj0"
GEO底层的实现原理其实就是Zset!我们可以用Zset命令来操作geo
示例:
127.0.0.1:6379> zrange China:city 0 -1 #查看所有城市
1) "chongqing"
2) "xian"
3) "shenzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
127.0.0.1:6379> zrem China:city beijing #移除指定城市
(integer) 1
127.0.0.1:6379> zrange China:city 0 -1
1) "chongqing"
2) "xian"
3) "shenzhen"
4) "hangzhou"
5) "shanghai"
2. Hyperloglog基数统计
上例中A集合和B集合中不重复的数1、3、5、7、8,所以基数=5.
简介:
Redis 2.8.9 版本就更新了Hyperloglog数据结构!
Redis Hyperloglog 基数统计的算法!
优点:占用的内存是固定的,2^64不同的元素基数,只需要费12KB内存!如果从内存角度比较就用Hyperloglog!
有0.81%错误率。
示例:网页的UV(一个人访问一个网站多次,但是还是算作一个人!)
-
传统的方式:set保存用户的id,然后就可以统计set中的元素数量作为标准判断!
这个方式如果保存大量的用户id,就会比较麻烦(占空间)!我们的目的是为了计数而不是保存用户id。
如果用Hyperloglog,很省空间,且0.81%错误率对于统计UV任务,可以忽略不计。
测试使用:
127.0.0.1:6379> PFADD mykey a b c d e f g h i j k # 创建第一组元素 mykey
(integer) 1
127.0.0.1:6379> pfcount mykey # 统计mykey中的基数数量
(integer) 11
127.0.0.1:6379> pfadd mykey2 i j k a b y t r e # 创建第二组元素 mykey2
(integer) 1
127.0.0.1:6379> pfcount mykey2 # 统计mykey中的基数数量
(integer) 9
127.0.0.1:6379> pfmerge mykey3 mykey mykey3 #合并两组 mykey mykey2 = mykey3 并集(去重)
OK
127.0.0.1:6379> pfcount mykey3
(integer) 11
如果允许容错,就选择Hyperloglog!
如果不允许容错,就用set或者自己的数据类型即可!
3. Bitmaps
位存储
常用场景:
1、统计用户信息:活跃or不活跃,登录or未登录,打卡,365打卡!两个状态的都可以使用Bitmaps!
Bitmaps位图,数据结构!都是操作二进制位来进行记录。就只有0和1两个状态。
365天=365bit 1字节=8bit 46字节左右!
测试
使用Bitmaps记录 周一到周日的打卡
查看某天是否打卡:
统计打卡的天数:(这样就可以看到是否有全勤)