Skip to content

Commit c6bf96e

Browse files
committed
[docs add ]Redis 3 种特殊数据结构详解
1 parent a77eb04 commit c6bf96e

File tree

5 files changed

+153
-12
lines changed

5 files changed

+153
-12
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ JVM 这部分内容主要参考 [JVM 虚拟机规范-Java8 ](https://docs.oracle
200200

201201
- [3种常用的缓存读写策略详解](docs/database/redis/3-commonly-used-cache-read-and-write-strategies.md)
202202
- [Redis 5 种基本数据结构详解](./docs/database/redis/redis-data-structures-01.md)
203+
- [Redis 3 种特殊数据结构详解](./docs/database/redis/redis-data-structures-02.md)
203204
- [Redis 内存碎片详解](./docs/database/redis/redis-memory-fragmentation.md)
204205
- [Redis 集群详解](./docs/database/redis/redis-cluster.md)
205206

docs/.vuepress/sidebar.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ export const sidebarConfig = defineSidebarConfig({
266266
children: [
267267
"3-commonly-used-cache-read-and-write-strategies",
268268
"redis-data-structures-01",
269+
"redis-data-structures-02",
269270
"redis-memory-fragmentation",
270271
"redis-cluster",
271272
],

docs/database/redis/redis-data-structures-01.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ title: Redis 5 种基本数据结构详解
33
category: 数据库
44
tag:
55
- Redis
6+
head:
7+
- - meta
8+
- name: keywords
9+
content: Redis常见数据结构
10+
- name: description
11+
content: Redis基础数据结构总结:String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)
612
---
713

814
你可以在 Redis 官网上找到 Redis 数据结构非常详细的介绍:

docs/database/redis/redis-data-structures-02.md

Lines changed: 128 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ title: Redis 3 种特殊数据结构详解
33
category: 数据库
44
tag:
55
- Redis
6+
head:
7+
- - meta
8+
- name: keywords
9+
content: Redis常见数据结构
10+
- name: description
11+
content: Redis特殊数据结构总结:HyperLogLogs(基数统计)、Bitmap (位存储)、Geospatial (地理位置)。
612
---
713

814
## Bitmap
@@ -22,9 +28,9 @@ Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需
2228
| SETBIT key offset value | 设置指定 offset 位置的值 |
2329
| GETBIT key offset | 获取指定 offset 位置的值 |
2430
| 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 |
2732

33+
**Bitmap 基本操作演示**
2834

2935
```bash
3036
# SETBIT 会返回之前位的值(默认是 0)这里会生成 7 个位
@@ -45,7 +51,7 @@ Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需
4551

4652
### 应用场景
4753

48-
**需要保存状态信息(0/1即可表示)的场景**
54+
**需要保存状态信息(0/1 即可表示)的场景**
4955

5056
- 举例 :用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)。
5157
- 相关命令 :`SETBIT``GETBIT``BITCOUNT``BITOP`
@@ -54,35 +60,146 @@ Bitmap 存储的是连续的二进制数字(0 和 1),通过 Bitmap, 只需
5460

5561
### 介绍
5662

57-
`HyperLogLog` 是一种有名的基数计数概率算法 ,并不是 Redis 特有的,Redis 只是实现了这个算法并提供了一些开箱即用的 API。
63+
HyperLogLog 是一种有名的基数计数概率算法 ,基于 LogLog Counting(LLC)优化改进得来,并不是 Redis 特有的,Redis 只是实现了这个算法并提供了一些开箱即用的 API。
5864

59-
Redis 提供的 `HyperLogLog` 占用空间非常非常小,只需要 12k 的空间就能存储接近`2^64`个不同元素。这是真的厉害,这就是数学的魅力么!并且,Redis 对 HyperLogLog 的存储结构做了优化,采用两种方式计数:
65+
Redis 提供的 HyperLogLog 占用空间非常非常小,只需要 12k 的空间就能存储接近`2^64`个不同元素。这是真的厉害,这就是数学的魅力么!并且,Redis 对 HyperLogLog 的存储结构做了优化,采用两种方式计数:
6066

6167
- **稀疏矩阵** :计数较少的时候,占用空间很小。
6268
- **稠密矩阵** :计数达到某个阈值的时候,占用 12k 的空间。
6369

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%` 。)。
6575

6676
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/image-20220720194154133.png)
6777

68-
`HyperLogLog` 的使用非常简单,但原理非常复杂。`HyperLogLog` 的原理以及在 Redis 中的实现可以看这篇文章:[HyperLogLog 算法的原理讲解以及 Redis 是如何应用它的](https://juejin.cn/post/6844903785744056333)
78+
HyperLogLog 的使用非常简单,但原理非常复杂。HyperLogLog 的原理以及在 Redis 中的实现可以看这篇文章:[HyperLogLog 算法的原理讲解以及 Redis 是如何应用它的](https://juejin.cn/post/6844903785744056333)
6979

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)
7181

7282
### 常用命令
7383

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 基本操作演示**
7493

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+
```
75112

76113
### 应用场景
77114

115+
**数量量巨大(百万、千万级别以上)的计数场景**
116+
117+
- 举例 :热门网站每日/每周/每月访问 ip 数统计、热门帖子 uv 统计、
118+
- 相关命令 :`PFADD``PFCOUNT`
119+
78120
## Geospatial index
79121

80-
地理空间数据管理。
122+
### 介绍
123+
124+
Geospatial index(地理空间索引,简称 GEO) 主要用于存储地理位置信息,基于 Sorted Set 实现。
125+
126+
通过 GEO 我们可以轻松实现两个位置距离的计算、获取指定位置附近的元素等功能。
81127

82128
![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/database/redis/image-20220720194359494.png)
83129

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`
85200

86201
## 参考
87202

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

docs/database/redis/redis-questions-01.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ Redis 5.0 新增加的一个数据结构 `Stream` 可以用来做消息队列,
122122
- **5 种基础数据结构** :String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)。
123123
- **3 种特殊数据结构** :HyperLogLogs(基数统计)、Bitmap (位存储)、Geospatial (地理位置)。
124124

125-
关于 5 种基础数据类型的详细介绍请看这篇文章:[Redis 5 种基本数据结构详解](./redis-data-structures-01.md)
125+
关于 5 种基础数据结构的详细介绍请看这篇文章:[Redis 5 种基本数据结构详解](./redis-data-structures-01.md)
126+
127+
关于 3 种特殊数据结构的详细介绍请看这篇文章:[Redis 3 种特殊数据结构详解](./redis-data-structures-02.md)
126128

127129
### String 的应用场景有哪些?
128130

@@ -199,6 +201,20 @@ Redis 中有一个叫做 `sorted set` 的数据结构经常被用在各种排行
199201
(integer) 2
200202
```
201203

204+
### 使用 HyperLogLog 统计页面 UV 怎么做?
205+
206+
1、将访问指定页面的每个用户 ID 添加到 `HyperLogLog` 中。
207+
208+
```bash
209+
PFADD PAGE_1:UV USER1 USER2 ...... USERn
210+
```
211+
212+
2、统计指定页面的 UV。
213+
214+
```bash
215+
PFCOUNT PAGE_1:UV
216+
```
217+
202218
## Redis 线程模型
203219

204220
### Redis 单线程模型了解吗?

0 commit comments

Comments
 (0)