Redis-三大特殊类型

三种特殊类型

geospatial

该数据类型是用来存储地理空间

附近的人,发送定位,分享实时位置,打车的时候的距离计算都可以通过这个实现

我们这里使用这几个城市的经纬度作为测试

城市 经度 维度
相城区 120.64239 31.36889
吴江区 120.638317 31.159815
太仓 121.10891 31.4497
常熟市 120.75225 31.65374
昆山市 120.98074 31.38464

这里有六个基本命令,我们来一个个看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# geoadd key longitude latitude member [longitude latitude member..]
# 增加一个经纬度的坐标
# 两极无法添加,一般我们通过java程序一次性导入
127.0.0.1:6379> geoadd Suzhou 120.64239 31.36889 XiangChengDistrict 120.638317 31.159815 WuJiangDistrict 121.10891 31.4497 TaiCang 120.75225 31.65374 ChangShuCity 120.98074 31.38464 KunShanCity
(integer) 5

# geodist key member1 member2 [unit]
# 获取两地之间的距离单位为米
127.0.0.1:6379> GEODIST Suzhou TaiCang WuJiangDistrict
"55133.1652"
127.0.0.1:6379> GEODIST Suzhou TaiCang KunShanCity km
"14.1556"

# geohash key member [member..]
# 获取member的二维的空间经纬度数据编码
# 这个可以csdn搜一下具体的算法实现
127.0.0.1:6379> geohash Suzhou TaiCang
1) "wtw4gvhzf10"

# geopos key member [member..]
# 查看member的经纬度
127.0.0.1:6379> geopos Suzhou TaiCang XiangChengDistrict
1) 1) "121.10891193151474"
2) "31.449701065685858"
2) 1) "120.64238995313644"
2) "31.368889085683811"

# georadius key longitude latitude radius m|km|ft|mi [WITHSCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC| ESC]
# mi是英里,ft是英尺
# 以给定的经纬度为中心,找到某一半径内的元素
# WITHCOORD表示显示坐标
# WITHDIST表示显示距离该点的位置
# WITHHASH表示显示该地址的hash值
# COUNT count表示显示几个
# ASC| ESC 表示正序还是倒序
127.0.0.1:6379> georadius Suzhou 120.98080 31.28460 30 km withdist
1) 1) "KunShanCity"
2) "11.1271"
2) 1) "TaiCang"
2) "22.0285"

# georadiusbymember key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC]
# 以member为中心radius为半径,找到在此范围中的元素
127.0.0.1:6379> georadiusbymember Suzhou TaiCang 30 km withcoord withdist withhash asc
1) 1) "TaiCang"
2) "0.0000"
3) (integer) 4054798020485654
4) 1) "121.10891193151474"
2) "31.449701065685858"
2) 1) "KunShanCity"
2) "14.1556"
3) (integer) 4054794184325796
4) 1) "120.98073989152908"
2) "31.38463984296795"

geo的底层其实是Zset,我们可以使用Zset的命令去操作geo

1
2
3
4
5
6
7
127.0.0.1:6379> zrem Suzhou TaiCang
(integer) 1
127.0.0.1:6379> zrange Suzhou 0 -1
1) "WuJiangDistrict"
2) "XiangChengDistrict"
3) "ChangShuCity"
4) "KunShanCity"

Hyperloglog

先来了解一下基数是什么?

基数其实就是一个集合中不重复的元素个数,其实就是一个集合去重后的集合长度

业务场景:

网站的访问量(一个人访问一个网站多次,也算一个人)

传统使用set集合的重复无序的特性,可以保存用户的id,以set集合的长度作为标准。但是,专门使用一个set来保存用户id未免优点奢侈,如果id是分布式的会很复杂,导致set集合很庞大,所以需要一个方法来解决这个问题。

Hyperloglog就是用来解决此问题的算法。

优点:占用很小的内存空间存放2^64个数据,也只占用12kb

瑕疵:会有0.81%的错误率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# pfadd key member [member..]
127.0.0.1:6379> pfadd set a b c d e f g h i j k l
(integer) 1

# pfcount key [key..]
# 返回基数
127.0.0.1:6379> pfcount set
(integer) 12
127.0.0.1:6379> pfadd set2 j k l m n
(integer) 1
127.0.0.1:6379> pfcount set set2
(integer) 14

# pfmerge destkey sourcekey [sourcekey..]
# 将sourcekey合并到destkey
127.0.0.1:6379> pfmerge set set2
OK

# 探究底层:
# 我们获取一下此数据的数据类型,可以看到实际上存储的是string
127.0.0.1:6379> type set
string
127.0.0.1:6379> get set
"HYLL\x01\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00Fm\x80I\xe8\x80@\xc4\x84K\\\x80D<\x848\x80B=\x80K\x83\x80B\xed\x84A\xfc\x8cG\x8e\x80Bm\x80BZ"

Bitmap

位存储,一般使用两种状态的区分

比如统计中国的男子和女子的数目

14亿个二进制数,0代表女子,1代表男

0 0 1 1 1 0 1 …

登录,头像是亮着的,未登录,头像是灰色的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# setbit key offset value
# 设置offset位是value
127.0.0.1:6379> setbit sign 0 0
(integer) 0
127.0.0.1:6379> setbit sign 1 1
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
# 中国sign可以代表
# 星期日未打卡
# 星期一已打卡
# 星期二未打卡
# 星期三已打卡

# getbit key offset
# 查看该天是否打卡
127.0.0.1:6379> getbit sign 3
(integer) 1

# bitcount key [start end]
# 查看sign中为1的个数
127.0.0.1:6379> BITCOUNT sign
(integer) 2
给作者买杯咖啡吧~~~