Skip to content

Commit 4685dd8

Browse files
committed
fix typo
1 parent 35adb48 commit 4685dd8

File tree

1 file changed

+20
-21
lines changed

1 file changed

+20
-21
lines changed

docs/database/Redis/redis-all.md

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java 面试突击》以及 Java 工程师必备学习资源。
22

3-
43
<!-- @import "[TOC]" {cmd="toc" depthFrom=1 depthTo=6 orderedList=false} -->
54

65
<!-- code_chunk_output -->
@@ -187,8 +186,8 @@ OK
187186

188187
#### 6.2. list
189188

190-
1. **介绍****list** 即是 **链表**。链表是一种非常常见的数据结构,特点是易于数据元素的插入和删除并且且可以灵活调整链表长度,但是链表的随机访问困难。许多高级编程语言都内置了链表的实现比如 Java 中的 **LinkedList**,但是 C 语言并没有实现链表,所以 Redis 实现了自己的链表数据结构。Redis 的 list 的实现为一个 **双向链表**,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。
191-
2. **常用命令:** `rpush,lpop,lpush,rpop,lrangellen` 等。
189+
1. **介绍****list** 即是 **链表**。链表是一种非常常见的数据结构,特点是易于数据元素的插入和删除并且可以灵活调整链表长度,但是链表的随机访问困难。许多高级编程语言都内置了链表的实现比如 Java 中的 **LinkedList**,但是 C 语言并没有实现链表,所以 Redis 实现了自己的链表数据结构。Redis 的 list 的实现为一个 **双向链表**,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。
190+
2. **常用命令:** `rpush,lpop,lpush,rpop,lrange,llen` 等。
192191
3. **应用场景:** 发布与订阅或者说消息队列、慢查询。
193192

194193
下面我们简单看看它的使用!
@@ -340,9 +339,9 @@ OK
340339

341340
#### 6.6 bitmap
342341

343-
1. **介绍 ** bitmap 存储的是连续的二进制数字(0 和 1),通过 bitmap, 只需要一个 bit 位来表示某个元素对应的值或者状态,key 就是对应元素本身 。我们知道 8 个 bit 可以组成一个 byte,所以 bitmap 本身会极大的节省储存空间。
342+
1. **介绍:** bitmap 存储的是连续的二进制数字(0 和 1),通过 bitmap, 只需要一个 bit 位来表示某个元素对应的值或者状态,key 就是对应元素本身 。我们知道 8 个 bit 可以组成一个 byte,所以 bitmap 本身会极大的节省储存空间。
344343
2. **常用命令:** `setbit``getbit``bitcount``bitop`
345-
3. **应用场景:** 适合需要保存状态信息(比如是否签到、是否登录...)并需要进一步对这些信息进行分析的场景。比如用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)。
344+
3. **应用场景** 适合需要保存状态信息(比如是否签到、是否登录...)并需要进一步对这些信息进行分析的场景。比如用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)。
346345

347346
```bash
348347
# SETBIT 会返回之前位的值(默认是 0)这里会生成 7 个位
@@ -375,7 +374,7 @@ OK
375374

376375
使用时间作为 key,然后用户 ID 为 offset,如果当日活跃过就设置为 1
377376

378-
那么我该如果计算某几天/月/年的活跃用户呢(暂且约定,统计时间内只有有一天在线就称为活跃),有请下一个 redis 的命令
377+
那么我该如何计算某几天/月/年的活跃用户呢(暂且约定,统计时间内只要有一天在线就称为活跃),有请下一个 redis 的命令
379378

380379
```bash
381380
# 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。
@@ -414,7 +413,7 @@ BITOP operation destkey key [key ...]
414413

415414
**使用场景三:用户在线状态**
416415

417-
对于获取或者统计用户在线状态,使用 bitmap 是一个节约空间效率又高的一种方法
416+
对于获取或者统计用户在线状态,使用 bitmap 是一个节约空间且效率又高的一种方法
418417

419418
只需要一个 key,然后用户 ID 为 offset,如果在线就设置为 1,不在线就设置为 0。
420419

@@ -424,17 +423,17 @@ BITOP operation destkey key [key ...]
424423

425424
**既然是单线程,那怎么监听大量的客户端连接呢?**
426425

427-
Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接(或者说是监听多个 socket),它会将感兴趣的事件及类型(读、写)注册到内核中并监听每个事件是否发生。
426+
Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接(或者说是监听多个 socket),它会将感兴趣的事件及类型读、写)注册到内核中并监听每个事件是否发生。
428427

429428
这样的好处非常明显: **I/O 多路复用技术的使用让 Redis 不需要额外创建多余的线程来监听客户端的大量连接,降低了资源的消耗**(和 NIO 中的 `Selector` 组件很像)。
430429

431-
另外, Redis 服务器是一个事件驱动程序,服务器需要处理两类事件: 1. 文件事件; 2. 时间事件。
430+
另外, Redis 服务器是一个事件驱动程序,服务器需要处理两类事件:1. 文件事件; 2. 时间事件。
432431

433432
时间事件不需要多花时间了解,我们接触最多的还是 **文件事件**(客户端进行读取写入等操作,涉及一系列网络通信)。
434433

435434
《Redis 设计与实现》有一段话是如是介绍文件事件的,我觉得写得挺不错。
436435

437-
> Redis 基于 Reactor 模式开发了自己的网络事件处理器:这个处理器被称为文件事件处理器(file event handler)。文件事件处理器使用 I/O 多路复用(multiplexing)程序来同时监听多个套接字,并根据 套接字目前执行的任务来为套接字关联不同的事件处理器
436+
> Redis 基于 Reactor 模式开发了自己的网络事件处理器:这个处理器被称为文件事件处理器(file event handler)。文件事件处理器使用 I/O 多路复用(multiplexing)程序来同时监听多个套接字,并根据套接字目前执行的任务来为套接字关联不同的事件处理器
438437
>
439438
> 当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关 闭(close)等操作时,与操作相对应的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。
440439
>
@@ -453,7 +452,7 @@ Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接(
453452

454453
### 8. Redis 没有使用多线程?为什么不使用多线程?
455454

456-
虽然说 Redis 是单线程模型,但是, 实际上,**Redis 在 4.0 之后的版本中就已经加入了对多线程的支持。**
455+
虽然说 Redis 是单线程模型,但是,实际上,**Redis 在 4.0 之后的版本中就已经加入了对多线程的支持。**
457456

458457
![redis4.0 more thread](images/redis-all/redis4.0-more-thread.png)
459458

@@ -466,14 +465,14 @@ Redis 通过**IO 多路复用程序** 来监听来自客户端的大量连接(
466465
我觉得主要原因有下面 3 个:
467466

468467
1. 单线程编程容易并且更容易维护;
469-
2. Redis 的性能瓶颈不再 CPU ,主要在内存和网络;
468+
2. Redis 的性能瓶颈不在 CPU ,主要在内存和网络;
470469
3. 多线程就会存在死锁、线程上下文切换等问题,甚至会影响性能。
471470

472471
### 9. Redis6.0 之后为何引入了多线程?
473472

474473
**Redis6.0 引入多线程主要是为了提高网络 IO 读写性能**,因为这个算是 Redis 中的一个性能瓶颈(Redis 的瓶颈主要受限于内存和网络)。
475474

476-
虽然,Redis6.0 引入了多线程,但是 Redis 的多线程只是在网络数据的读写这类耗时操作上使用了, 执行命令仍然是单线程顺序执行。因此,你也不需要担心线程安全问题。
475+
虽然,Redis6.0 引入了多线程,但是 Redis 的多线程只是在网络数据的读写这类耗时操作上使用了,执行命令仍然是单线程顺序执行。因此,你也不需要担心线程安全问题。
477476

478477
Redis6.0 的多线程默认是禁用的,只使用主线程。如需开启需要修改 redis 配置文件 `redis.conf`
479478

@@ -501,15 +500,15 @@ io-threads 4 #官网建议4核的机器建议设置为2或3个线程,8核的
501500
Redis 自带了给缓存数据设置过期时间的功能,比如:
502501

503502
```bash
504-
127.0.0.1:6379> exp key 60 # 数据在 60s 后过期
503+
127.0.0.1:6379> exp key 60 # 数据在 60s 后过期
505504
(integer) 1
506505
127.0.0.1:6379> setex key 60 value # 数据在 60s 后过期 (setex:[set] + [ex]pire)
507506
OK
508507
127.0.0.1:6379> ttl key # 查看数据还有多久过期
509508
(integer) 56
510509
```
511510

512-
注意:**Redis 中除了字符串类型有自己独有设置过期时间的命令 `setex` 外,其他方法都需要依靠 `expire` 命令来设置过期时间 。另外, `persist` 命令可以移除一个键的过期时间 **
511+
注意:**Redis 中除了字符串类型有自己独有设置过期时间的命令 `setex` 外,其他方法都需要依靠 `expire` 命令来设置过期时间 。另外, `persist` 命令可以移除一个键的过期时间 **
513512

514513
**过期时间除了有助于缓解内存的消耗,还有什么其他用么?**
515514

@@ -548,7 +547,7 @@ typedef struct redisDb {
548547

549548
但是,仅仅通过给 key 设置过期时间还是有问题的。因为还是可能存在定期删除和惰性删除漏掉了很多过期 key 的情况。这样就导致大量过期 key 堆积在内存里,然后就 Out of memory 了。
550549

551-
怎么解决这个问题呢?答案就是: **Redis 内存淘汰机制。**
550+
怎么解决这个问题呢?答案就是:**Redis 内存淘汰机制。**
552551

553552
### 13. Redis 内存淘汰机制了解么?
554553

@@ -565,7 +564,7 @@ Redis 提供 6 种数据淘汰策略:
565564

566565
4.0 版本后增加以下两种:
567566

568-
7. **volatile-lfu(least frequently used)**:从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰
567+
7. **volatile-lfu(least frequently used)**:从已设置过期时间的数据集server.db[i].expires中挑选最不经常使用的数据淘汰
569568
8. **allkeys-lfu(least frequently used)**:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key
570569

571570
### 14. Redis 持久化机制(怎么保证 Redis 挂掉之后再重启数据可以进行恢复)
@@ -590,7 +589,7 @@ save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生
590589

591590
**AOF(append-only file)持久化**
592591

593-
与快照持久化相比,AOF 持久化 的实时性更好,因此已成为主流的持久化方案。默认情况下 Redis 没有开启 AOF(append only file)方式的持久化,可以通过 appendonly 参数开启:
592+
与快照持久化相比,AOF 持久化的实时性更好,因此已成为主流的持久化方案。默认情况下 Redis 没有开启 AOF(append only file)方式的持久化,可以通过 appendonly 参数开启:
594593

595594
```conf
596595
appendonly yes
@@ -622,7 +621,7 @@ AOF 重写可以产生一个新的 AOF 文件,这个新的 AOF 文件和原有
622621

623622
AOF 重写是一个有歧义的名字,该功能是通过读取数据库中的键值对来实现的,程序无须对现有 AOF 文件进行任何读入、分析或者写入操作。
624623

625-
在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新旧两个 AOF 文件所保存的数据库状态一致。最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作
624+
在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新旧两个 AOF 文件所保存的数据库状态一致。最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作
626625

627626
### 15. Redis 事务
628627

@@ -640,7 +639,7 @@ QUEUED
640639
2) "Guide哥"
641640
```
642641

643-
使用 [`MULTI`](https://redis.io/commands/multi)命令后可以输入多个命令。Redis 不会立即执行这些命令,而是将它们放到队列,当调用了[`EXEC`](https://redis.io/commands/exec)命令将执行所有命令。
642+
使用 [`MULTI`](https://redis.io/commands/multi) 命令后可以输入多个命令。Redis 不会立即执行这些命令,而是将它们放到队列,当调用了 [`EXEC`](https://redis.io/commands/exec) 命令将执行所有命令。
644643

645644
这个过程是这样的:
646645

@@ -809,7 +808,7 @@ Cache Aside Pattern 中遇到写请求是这样的:更新 DB,然后直接删
809808
如果更新数据库成功,而删除缓存这一步失败的情况的话,简单说两个解决方案:
810809

811810
1. **缓存失效时间变短(不推荐,治标不治本)** :我们让缓存数据的过期时间变短,这样的话缓存就会从数据库中加载数据。另外,这种解决办法对于先操作缓存后操作数据库的场景不适用。
812-
2. **增加 cache 更新重试机制(常用)**: 如果 cache 服务当前不可用导致缓存删除失败的话,我们就隔一段时间进行重试,重试次数可以自己定。如果多次重试还是失败的话,我们可以把当前更新失败的 key 存入队列中,等缓存服务可用之后,再将 缓存中对应的 key 删除即可。
811+
2. **增加 cache 更新重试机制(常用)**: 如果 cache 服务当前不可用导致缓存删除失败的话,我们就隔一段时间进行重试,重试次数可以自己定。如果多次重试还是失败的话,我们可以把当前更新失败的 key 存入队列中,等缓存服务可用之后,再将缓存中对应的 key 删除即可。
813812

814813
### 19. 参考
815814

0 commit comments

Comments
 (0)