@@ -3,6 +3,12 @@ title: Redis 3 种特殊数据结构详解
3
3
category : 数据库
4
4
tag :
5
5
- Redis
6
+ head :
7
+ - - meta
8
+ - name : keywords
9
+ content : Redis常见数据结构
10
+ - name : description
11
+ content : Redis特殊数据结构总结:HyperLogLogs(基数统计)、Bitmap (位存储)、Geospatial (地理位置)。
6
12
---
7
13
8
14
## Bitmap
@@ -22,9 +28,9 @@ Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需
22
28
| SETBIT key offset value | 设置指定 offset 位置的值 |
23
29
| GETBIT key offset | 获取指定 offset 位置的值 |
24
30
| BITCOUNT key start end | 获取 start 和 end 之前值为 1 的元素个数 |
25
- | BITOP operation destkey key1 key2 ... | 对一个或多个 Bitmap 进行运算,可用运算符有AND, OR, XOR以及NOT |
26
-
31
+ | BITOP operation destkey key1 key2 ... | 对一个或多个 Bitmap 进行运算,可用运算符有 AND, OR, XOR 以及 NOT |
27
32
33
+ ** Bitmap 基本操作演示** :
28
34
29
35
``` bash
30
36
# SETBIT 会返回之前位的值(默认是 0)这里会生成 7 个位
@@ -45,7 +51,7 @@ Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需
45
51
46
52
### 应用场景
47
53
48
- ** 需要保存状态信息(0/1即可表示 )的场景**
54
+ ** 需要保存状态信息(0/1 即可表示 )的场景**
49
55
50
56
- 举例 :用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)。
51
57
- 相关命令 :` SETBIT ` 、` GETBIT ` 、` BITCOUNT ` 、` BITOP ` 。
@@ -54,35 +60,146 @@ Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需
54
60
55
61
### 介绍
56
62
57
- ` HyperLogLog ` 是一种有名的基数计数概率算法 ,并不是 Redis 特有的,Redis 只是实现了这个算法并提供了一些开箱即用的 API。
63
+ HyperLogLog 是一种有名的基数计数概率算法 ,基于 LogLog Counting(LLC)优化改进得来 ,并不是 Redis 特有的,Redis 只是实现了这个算法并提供了一些开箱即用的 API。
58
64
59
- Redis 提供的 ` HyperLogLog ` 占用空间非常非常小,只需要 12k 的空间就能存储接近` 2^64 ` 个不同元素。这是真的厉害,这就是数学的魅力么!并且,Redis 对 HyperLogLog 的存储结构做了优化,采用两种方式计数:
65
+ Redis 提供的 HyperLogLog 占用空间非常非常小,只需要 12k 的空间就能存储接近` 2^64 ` 个不同元素。这是真的厉害,这就是数学的魅力么!并且,Redis 对 HyperLogLog 的存储结构做了优化,采用两种方式计数:
60
66
61
67
- ** 稀疏矩阵** :计数较少的时候,占用空间很小。
62
68
- ** 稠密矩阵** :计数达到某个阈值的时候,占用 12k 的空间。
63
69
64
- 不过, ` HyperLogLog ` 的计数结果并不是一个精确值,存在一定的误差(标准误差为 ` 0.81% ` 。),这是由于它本质上是用概率算法导致的。
70
+ Redis 官方文档中有对应的详细说明:
71
+
72
+ ![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/image-20220721091424563.png )
73
+
74
+ 基数计数概率算法为了节省内存并不会直接存储元数据,而是通过一定的概率统计方法预估基数值(集合中包含元素的个数)。因此, HyperLogLog 的计数结果并不是一个精确值,存在一定的误差(标准误差为 ` 0.81% ` 。)。
65
75
66
76
![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/image-20220720194154133.png )
67
77
68
- ` HyperLogLog ` 的使用非常简单,但原理非常复杂。` HyperLogLog ` 的原理以及在 Redis 中的实现可以看这篇文章:[ HyperLogLog 算法的原理讲解以及 Redis 是如何应用它的] ( https://juejin.cn/post/6844903785744056333 ) 。
78
+ HyperLogLog 的使用非常简单,但原理非常复杂。HyperLogLog 的原理以及在 Redis 中的实现可以看这篇文章:[ HyperLogLog 算法的原理讲解以及 Redis 是如何应用它的] ( https://juejin.cn/post/6844903785744056333 ) 。
69
79
70
- 再推荐一个可以帮助理解HyperLogLog原理的工具 :[ Sketch of the Day: HyperLogLog — Cornerstone of a Big Data Infrastructure] ( http://content.research.neustar.biz/blog/hll.html ) 。
80
+ 再推荐一个可以帮助理解 HyperLogLog 原理的工具 :[ Sketch of the Day: HyperLogLog — Cornerstone of a Big Data Infrastructure] ( http://content.research.neustar.biz/blog/hll.html ) 。
71
81
72
82
### 常用命令
73
83
84
+ HyperLogLog 相关的命令非常少,最常用的也就 3 个。
85
+
86
+ | 命令 | 介绍 |
87
+ | ----------------------------------------- | ------------------------------------------------------------ |
88
+ | PFADD key element1 element2 ... | 添加一个或多个元素到 HyperLogLog 中 |
89
+ | PFCOUNT key1 key2 | 获取一个或者多个 HyperLogLog 的唯一计数。 |
90
+ | PFMERGE destkey sourcekey1 sourcekey2 ... | 将多个 HyperLogLog 合并到 destkey 中,destkey 会结合多个源,算出对应的唯一计数。 |
91
+
92
+ ** HyperLogLog 基本操作演示** :
74
93
94
+ ``` bash
95
+ > PFADD hll foo bar zap
96
+ (integer) 1
97
+ > PFADD hll zap zap zap
98
+ (integer) 0
99
+ > PFADD hll foo bar
100
+ (integer) 0
101
+ > PFCOUNT hll
102
+ (integer) 3
103
+ > PFADD some-other-hll 1 2 3
104
+ (integer) 1
105
+ > PFCOUNT hll some-other-hll
106
+ (integer) 6
107
+ > PFMERGE desthll hll some-other-hll
108
+ " OK"
109
+ > PFCOUNT desthll
110
+ (integer) 6
111
+ ```
75
112
76
113
### 应用场景
77
114
115
+ ** 数量量巨大(百万、千万级别以上)的计数场景**
116
+
117
+ - 举例 :热门网站每日/每周/每月访问 ip 数统计、热门帖子 uv 统计、
118
+ - 相关命令 :` PFADD ` 、` PFCOUNT ` 。
119
+
78
120
## Geospatial index
79
121
80
- 地理空间数据管理。
122
+ ### 介绍
123
+
124
+ Geospatial index(地理空间索引,简称 GEO) 主要用于存储地理位置信息,基于 Sorted Set 实现。
125
+
126
+ 通过 GEO 我们可以轻松实现两个位置距离的计算、获取指定位置附近的元素等功能。
81
127
82
128
![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/image-20220720194359494.png )
83
129
84
- ## Stream
130
+ ### 常用命令
131
+
132
+ | 命令 | 介绍 |
133
+ | ------------------------------------------------ | ------------------------------------------------------------ |
134
+ | GEOADD key longitude1 latitude1 member1 ... | 添加一个或多个元素对应的经纬度信息到 GEO 中 |
135
+ | GEOPOS key member1 member2 ... | 返回给定元素的经纬度信息 |
136
+ | GEODIST key member1 member2 M/KM/FT/MI | 返回两个给定元素之间的距离 |
137
+ | GEORADIUS key longitude latitude radius distance | 获取指定位置附近 distance 范围内的其他元素,支持 ASC(由近到远)、DESC(由远到近)、Count(数量) 等参数 |
138
+ | GEORADIUSBYMEMBER key member radius distance | 类似于 GEORADIUS 命令,只是参照的中心点是 GEO 中的元素 |
139
+
140
+ ** 基本操作** :
141
+
142
+ ``` bash
143
+ > GEOADD personLocation 116.33 39.89 user1 116.34 39.90 user2 116.35 39.88 user3
144
+ 3
145
+ > GEOPOS personLocation user1
146
+ 116.3299986720085144
147
+ 39.89000061669732844
148
+ > GEODIST personLocation user1 user2 km
149
+ 1.4018
150
+ ```
151
+
152
+ 通过 Redis 可视化工具查看 ` personLocation ` ,果不其然,底层就是 Sorted Set。
153
+
154
+ GEO 中存储的地理位置信息的经纬度数据通过 GeoHash 算法转换成了一个整数,这个整数作为 Sorted Set 的 score(权重参数)使用。
155
+
156
+ ![ ] ( https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/image-20220721201545147.png )
157
+
158
+ ** 获取指定位置范围内的其他元素** :
159
+
160
+ ``` bash
161
+ > GEORADIUS personLocation 116.33 39.87 3 km
162
+ user3
163
+ user1
164
+ > GEORADIUS personLocation 116.33 39.87 2 km
165
+ > GEORADIUS personLocation 116.33 39.87 5 km
166
+ user3
167
+ user1
168
+ user2
169
+ > GEORADIUSBYMEMBER personLocation user1 5 km
170
+ user3
171
+ user1
172
+ user2
173
+ > GEORADIUSBYMEMBER personLocation user1 2 km
174
+ user1
175
+ user2
176
+ ```
177
+
178
+ ` GEORADIUS ` 命令的底层原理解析可以看看阿里的这篇文章:[ Redis 到底是怎么实现“附近的人”这个功能的呢?] ( https://juejin.cn/post/6844903966061363207 ) 。
179
+
180
+ ** 移除元素** :
181
+
182
+ GEO 底层是 Sorted Set ,你可以对 GEO 使用 Sorted Set 相关的命令。
183
+
184
+ ``` bash
185
+ > ZREM personLocation user1
186
+ 1
187
+ > ZRANGE personLocation 0 -1
188
+ user3
189
+ user2
190
+ > ZSCORE personLocation user2
191
+ 4069879562983946
192
+ ```
193
+
194
+ ### 应用场景
195
+
196
+ ** 需要管理使用地理空间数据的场景**
197
+
198
+ - 举例:附近的人。
199
+ - 相关命令: ` GEOADD ` 、` GEORADIUS ` 、` GEORADIUSBYMEMBER ` 。
85
200
86
201
## 参考
87
202
88
- -
203
+ - Redis Data Structures :https://redis.com/redis-enterprise/data-structures/ 。
204
+ - 《Redis 深度历险:核心原理与应用实践》1.6 四两拨千斤——HyperLogLog
205
+ - 布隆过滤器,位图,HyperLogLog:https://hogwartsrico.github.io/2020/06/08/BloomFilter-HyperLogLog-BitMap/index.html
0 commit comments