【redis进阶】redis 总结

embedded/2025/1/31 17:23:30/

目录

介绍一下什么是 Redis,有什么特点

Redis 支持哪些数据类型

Redis 数据类型底层的数据结构/编码方式是什么

ZSet 为什么使用跳表,而不是使用红黑树来实现

Redis 的常见应用场景有哪些

怎样测试 Redis 服务器的连通性

如何设置 key 的过期时间

Redis 为什么是单线程模型

Redis ⾥的 IO 多路复⽤是怎么回事

Redis 的持久化机制有哪些

RDB 的持久化触发条件是怎样的

AOF 的⽂件同步策略有哪些

AOF 的重写机制是怎样的

Redis 的 key 的过期删除策略是怎样的

如果⼤量的 key 在同⼀时间点过期,会产⽣什么问题? 如何处理?

Redis 的淘汰策略是怎样的

Redis 如果内存⽤完了, 会出现什么情况

Redis 为什么把数据放到内存中

Redis  的主从同步/主从复制是怎么回事

Redis 的 pipeline (流⽔线/管道) 是什么

介绍下 Redis 哨兵

Redis 哨兵如果发现主节点宕机了, 接下来会做哪些事情

Redis 的集群是⼲什么的

Redis 的哈希槽是怎么回事

Redis 集群的最⼤节点个数是多少

Redis 集群会有些操作丢失吗

Redis 集群如何选择数据库

介绍下⼀致性哈希算法

如何理解 Redis 的事务? 和 MySQL 的事务有啥区别?

Redis 和事务相关的命令有哪些

为什么在⽣产环境上不应该使⽤ keys *  命令

如何使⽤ Redis 作为消息队列

如何使⽤ Redis 实现分布式锁

什么是缓存穿透, 缓存雪崩, 缓存击穿

什么是热 key 问题? 如何解决?

如何实现 Redis ⾼可⽤

Redis 和 MySQL 如何保证双写⼀致性

⽣成 RDB 期间, Redis 是否可以处理写请求

Redis 的常⽤管理命令有哪些

Redis ⽤到的⽹络通讯协议是怎样的

Redis 如何遍历 key

Redis 如何实现 "查找附近的⼈" 

什么是 Redis 的 "bigkey" 问题? 如何解决?

redis%20%E6%BA%90%E7%A0%81-toc" name="tableOfContents" style="margin-left:80px">阅读 redis 源码


redis学习🥳

介绍一下什么是 Redis,有什么特点

Redis 是一个高性能的 key-value 内存数据库.

不同于传统的 MySQL 这样的关系型数据库,Redis 主要使用内存存储数据 (当然也支持持久化存储到

硬盘上),并非是使用 "表" 这样的结构来组织数据,而是使用键值对的方式.

Redis 没有关系型数据库的复杂查询以及约束等功能,换来的是简单易用和更高的性能.

特点:

  • 使用内存存储 (高性能).
  • 支持多种数据结构(string、list、hash、set、zset等).
  • 支持持久化(rdb 和 aof).
  • 单线程处理请求.
  • 支持主从复制.
  • 支持哨兵模式.
  • 支持集群模式.
  • 支持事务.
  • 支持多语言客户端.
  • ......

参考资料:https://redis.io/docs/about/

Redis 支持哪些数据类型

五种最核心的类型:

  • String
  • List
  • Hash
  • Set
  • ZSet

在后续版本中也逐渐新增了一些新的数据类型:

  • Bitmap:通过二进制位表示某个数字是否存在.
  • Bitfield:把字符串当做位图,并进行位操作.
  • Hyperloglog:基于位图的结构实现 "计数" 效果(统计某个数字出现几次, 比 hashmap节省空间).
  • Geospatial:地理信息,存储经纬度. 并且可以进行一些空间计算 (比如找出某个点附近 1km 内都有哪些点).
  • Stream:消息队列.

这几个类型都属于特定场景中才会使用的类型. 不像前面五个类型通用性那么强. 因此我们课堂中没有介绍. 大家感兴趣可以自行了解.

参考资料: https://redis.io/docs/data-types/

Redis 数据类型底层的数据结构/编码方式是什么

  • embstr:是针对短字符串的优化实现. 小于等于 39 字节的字符串使用 embstr, 大于则使用 raw.
  • ziplist:压缩列表. 本质上是个字节数组. 可以节省内存空间. 当有序集合、哈希表、列表元素少,并且元素都是短字符串的时候,会使用这个.
  • linklist:链表. 需要额外内存开销,容易引入内存碎片.
  • skiplist:跳表,能够 O(logN) 的复杂度进行查找元素的复杂链表.
  • quicklist:是个链表,每个元素是一个 ziplist.
  • listpack:从 Redis 7 开始,引入了新的数据结构 listpack, 用来代替 ziplist

使用哪种编码,是 redis 内部自动决定的,使用 object encoding key 来查看编码.

ZSet 为什么使用跳表,而不是使用红黑树来实现

跳表的插入 / 查询 / 删除时间复杂度都是 O(logN),和红黑树是一样的.

但是跳表实现起来更简单. 而且不需要重新平衡这样的操作.

Redis 的常见应用场景有哪些

  • 缓存:一些经常被访问到的热点数据,可以使用 Redis 进行缓存,降低查询数据库的次数.
  • 计数器:统计点击次数 / 访问次数 / 收藏次数等常见需求.
  • 排行榜:可以基于 Redis 的 ZSet 轻松实现.
  • 分布式会话:使用 Redis 存储会话信息,可以使用户访问到系统的不同模块时都使用同一个公共的会话.
  • 分布式锁:对于分布式系统的并发访问控制,可以基于 Redis 来实现分布式锁,避免并发的竞争问题(类似于线程安全问题).
  • 消息队列:Redis 自身支持 Stream 数据类型,可以作为简单的消息队列使用.
  • ......

怎样测试 Redis 服务器的连通性

使用 ping 命令即可. 如果连通,服务器会返回 pong

如何设置 key 的过期时间

可以在 set 的时候通过 EX 选项指定过期时间. 也可以通过 expire 命令单独指定.

Redis 为什么是单线程模型

Redis 内部的逻辑比较简单,一般的性能瓶颈都是出现在 内存 或者 IO 上,很少是 CPU . 因此使用多

线程并没有太大的收益,反而可能会引入线程安全问题.

从 6.0 开始,Redis 引入多线程. 此时只是使用多个线程去处理 网络请求+协议解析,真正执行仍然是

单线程完成的. 这样做可以进一步提高 IO 的处理效率.

Redis ⾥的 IO 多路复⽤是怎么回事

Redis 主要是基于了 Linux 提供的 epoll 机制来完成 IO 多路复⽤.

简单的说,所谓的 "IO多路复⽤" 就是⽤⼀个线程,来管理多个 socket (⽂件描述符), 并按需激活线程.

虽然⼀个 Redis 服务器要处理很多个客⼾端的请求, 但是这些客⼾端的请求并⾮是 "同⼀时刻" 到达的.

在⼀个单位时间内, 可能只有两三个客⼾端的请求到来了. 因此如果使⽤传统的每个线程处理⼀个连接的⽅式实现, ⼤部分线程其实都是挂起的(不活跃的).

因此与其搞了⼀堆线程, 但是线程在摸⻥, 还不如就⽤⼀个线程来处理了.上述这样的需求, 被操作系统内

核封装好了. 就是 IO 多路复⽤.

Linux 中, IO 多路复⽤有三种实现:

  • select
  • poll
  • epoll

其中 epoll 是最新的版本 (2005 年左右引⼊的), 也是最⾼效的版本.

epoll 在内核中维护了⼀个红⿊树, 来管理所有的 socket, 并且每个节点都关联了⼀个事件回调. 当系统内核感知到⽹卡收到数据了, 进⼀步判定这个数据是给哪个 socket 的, 随之调⽤对应的回调, 进⼀步唤醒⽤⼾线程, 来处理这个收到的数据.

此时这个⽤⼾线程是 "忙碌" 的, 要不停的处理来⾃各个客⼾端的请求数据.

Redis 的持久化机制有哪些

RDB 和 AOF:参考⽂档前⾯的章节 "第四章 持久化".

RDB 的持久化触发条件是怎样的

• ⼿动触发:使⽤ save 或者 bgsave 即可触发持久化.

• ⾃动触发:

  • 在配置⽂件中通过 save m n  即可设定 m 秒内发⽣ n 次修改, 就触发持久化
  • 从节点进⾏全量复制操作, 触发持久化.
  • 执⾏ shutdown 命令, 关闭 redis server, 触发持久化.

AOF 的⽂件同步策略有哪些

可配置值

说明

always

命令写⼊ aof_buf 后调⽤ fsync 同步,完成后返回

everysec

命令写⼊aof_buf 后只执⾏ write 操作,不进⾏ fsync。每秒由同步线程进⾏ fsync。

no

命令写⼊ aof_buf 后只执⾏ write 操作,由 OS 控制 fsync 频率。

AOF 的重写机制是怎样的

参考⽂档前⾯的章节 "第四章 持久化".

Redis 的 key 的过期删除策略是怎样的

惰性过期

只有当访问⼀个key时,才会判断该key是否已过期,过期则清除。该策略可以最⼤化地节省CPU资源,却对内存⾮常不友好。极端情况可能出现⼤量的过期key没有再次被访问,从⽽不会被清除,占⽤⼤量内存。

定期过期

每隔⼀定的时间,会扫描⼀定数量的数据库的expires字典中⼀定数量的key,并清除其中已过期的 key。该策略是前两者的⼀个折中⽅案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。

expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表⽰的过期时间。键空间是指该Redis集群中保存的所有键。

Redis 中同时使⽤了惰性过期和定期过期两种过期策略。

  • 每隔 100ms 就随机抽取⼀定数量的key来检查和删除的。
  • 在获取某个key的时候,redis 会检查⼀下,这个 key 如果设置了过期时间并且已经过期了,此时就会删除。

如果⼤量的 key 在同⼀时间点过期,会产⽣什么问题? 如何处理?

如果⼤量的 key 过期时间设置的过于集中,到过期的那个时间点,Redis 可能会出现短暂的卡顿现象。为何会出现卡顿呢? Redis 针对过期 key 的删除, 采取 定期采样删除 + 惰性删除 两种⽅式结合.

对于定期采样删除来说, Redis 会注册⼀个定时器, 每隔⼀定时间触发⼀次采样删除.在删除的时候会先根据事先统计好的过期 key 的个数来决定后续策略.

如果过期 key 的数⽬超过总 key 数⽬的 25% 以上, 就会使 Redis 持续删除过期 key 直到最⼤时间删除时间 (默认是 25ms).

之所以限制这个最⼤时间, 就是为了防⽌ Redis 被卡住太久

但是即使如此, 有些对性能要求较⾼的场景仍然会因为阻塞 25ms 导致性能下降严重.

解决⽅案:  可以在过期时间上加⼀个随机值,使得过期时间分散⼀些.

很多时候过期时间并不⼀定⾮得卡的那么精准. ⽐如设定 2s 之后过期, 不⼀定⾮要正好的 2000ms, 2001, 2002, 1999, 1998 甚⾄ 2010 这些时间都是问题不⼤的.

因此让过期时间通过随机值分散, 就可以避免同⼀时刻过期的 key 太多, 从⽽降低触发 25% 这个阈值的可能性.

Redis 的淘汰策略是怎样的

当 Redis 内存不⾜时, 如果继续尝试添加新的 key, 就会触发淘汰策略, 把之前的旧 key 给⾃动删除掉.

Redis 提供的淘汰策略有以下⼏种:

 volatile-lru 当内存不足以容纳新写入数据时,从设置了过期时间的key中使用LRU(最近最少使用)算法进行淘汰

 allkeys-lru 当内存不足以容纳新写入数据时,从所有key中使用LRU(最近最少使用)算法进行淘汰.

 volatile-lfu 4.0版本新增,当内存不足以容纳新写入数据时,在过期的key中,使用LFU算法进行删除key.

 allkeys-lfu 4.0版本新增,当内存不足以容纳新写入数据时,从所有key中使用LFU算法进行淘汰.

 volatile-random 当内存不足以容纳新写入数据时,从设置了过期时间的key中,随机淘汰数据.

 allkeys-random 当内存不足以容纳新写入数据时,从所有key中随机淘汰数据.

 volatile-ttl 在设置了过期时间的key中,根据过期时间进行淘汰,越早过期的优先被淘汰.(相当于 FIFO, 只不过是局限于过期的 key)

 noeviction 默认策略,当内存不足以容纳新写入数据时,新写入操作会报错.

🦄 关于 LRU 和 LFU

LRU:Least Recently Used 最近最久使用算法. 哪个 key 上次访问时间最长,就干掉.

LFU:Least Frequently Used 最近最常使用算法. 哪个 key 在最近一段时间里使用次数最少,就干掉.

在上述策略中,  默认策略⼀般来说都是⽐较好的选择.

  • 部署 Redis 的机器正常来说不应该消耗到内存耗尽才做处理. 应该有完善的监控报警体系, 当内存接近上限的时候提前通知程序猿, 尽早进⾏扩容.
  • 如果确实出现内存耗尽了, 相⽐于 Redis 偷偷的删除⼀部分 key, 带伤运⾏(当然, volatile 前缀系列的策略不算带伤), 不如尽早显式的把问题暴露出来, 及时处理.
  • 除⾮是 Redis 中的数据完全不关键, 否则不应该使⽤ allkeys 系列的策略.

Redis 如果内存⽤完了, 会出现什么情况

会触发 Redis 的淘汰策略, 把⼀些 key ⾃动删除掉.参考上个问题.

Redis 为什么把数据放到内存中

效率.

访问内存的速度⽐访问硬盘的速度快 3-4 个数量级.

如下表可以看到:

层级

速度

L1 cache reference

0.5 ns

Branch mispredict

5 ns

L2 cache reference

7 ns

Mutex lock/unlock

25 ns

Main memory reference

100 ns

Compress 1 K bytes with Zippy

3 000 ns

Send 2 K bytes over 1 Gbps network

20 000 ns

Read 1 MB sequentially from Memory

250 000 ns

Round trip within same datacenter

500 000 ns

Disk seek

10 000 000 ns

Read 1 MB sequentially from disk

20 000 000 ns

Send packet CA -> Netherlands -> CA

150 000 000 ns

进⾏⼀次内存的随机访问操作是 100ns

进⾏⼀次硬盘的随机访问操作是 10 000 000 ns

这个差距还是⾮常明显的.

因此使⽤内存存储数据让 Redis 相⽐于 MySQL 等数据库, 具有了⾮常显著的优势. 当然, 使⽤内存存储的劣势也是⽐较明显的:

  • 内存的存储空间⽐硬盘⼩很多. 不过随着硬件的发展, ⼤内存的服务器越来越便宜了, 市⾯上甚⾄可以看到 1TB 级别的内存的机器了.
  • 内存的数据掉电后会丢失. 因此 Redis 引⼊持久化的⽅式, 把数据在硬盘上也备份⼀遍(当然, 增删改查仍然是以内存为主), 速度不影响的前提下, 保证重启后数据不丢失.

Redis  的主从同步/主从复制是怎么回事

解决的问题:

  • 提⾼ Redis 的可⽤性, 避免 Redis 机器/进程 挂了之后⽆法提供服务
  • 降低 Redis 服务器的压⼒, 从节点读, 主节点写, 让单个节点承担的压⼒更⼩.

需要有多个服务器, 部署多个 Redis 服务器程序. 其中⼀个作为主节点, 其他作为从节点.

在从节点 Redis 启动的时候, 通过配置⽂件或者命令参数 --slaveof 指定当前节点的主节点是哪个.

当从节点启动之后, 就会清空⾃⾝数据, 并把主节点的所有数据都复制过来. 并且主节点的数据后续如果

进⾏修改, 从节点也能⾃动随之更新.

主节点可以写数据也可以读数据.  从节点只能读数据.

这样的话, 主节点的数据就多了⼏个 "备份", 当主节点挂了仍然可以通过从节点来读取数据.另⼀⽅⾯访

问 Redis ⼤多还是读操作, 通过从节点就可以分担主节点的读操作的压⼒.

💡 比如一个 Redis 每单位时间要处理 100 次写请求,和 10w 次读请求.

如果使用主从的方式部署,比如一个主节点,三个从节点,此时主节点负责处理 100 次写请求,主节点和从节点再负责处理 2.5w 次读请求.

这样主节点的压力就降低到了原来的 1/4了.

Redis 的 pipeline (流⽔线/管道) 是什么

在 Redis 客⼾端执⾏ N 个命令, ⼤概的过程如下:

发送命令-> 命令排队-> 命令执行-> 返回结果
发送命令-> 命令排队-> 命令执行-> 返回结果
发送命令-> 命令排队-> 命令执行-> 返回结果
发送命令-> 命令排队-> 命令执行-> 返回结果
......

这个过程称为 Round trip time (简称RTT, 往返时间) .

如果我们需要执⾏多个操作, 就需要多个这样的 RTT . 其中⼤量的时间都消耗在 发送命令/返回结果 的

⽹络时间上了.

使⽤ pipeline, 就可以把多个 redis 命令, 合并到⼀个请求中, 节省⽹络开销.

发送命令-> 命令排队-> 命令排队-> 命令排队-> 命令执行 -> 命令执行-> 命令执行-> 返回结果

🏕 注意! pipeline 中的这 N 个命令的执行并非是原子的! 他们只是同乘一趟地铁的陌路人,

彼此之间没啥关联关系.

通过 Redis 客⼾端使⽤管道, 可以基于 Linux 的管道实现. ⽐如把要执⾏的 N 个命令写⼊ cmd.txt ⽂本⽂件中, 每个命令⼀⾏.

然后执⾏

cat cmd.txt | redis-cli --pipe

通过 pipe 参数即可让 redis-cli 读取执⾏ cmd.txt 中的内容.

如果通过管道执⾏的命令太多, 可能会使服务器被阻塞住.

介绍下 Redis 哨兵

参考⽂档前⾯的章节 "第七章 哨兵"

Redis 哨兵如果发现主节点宕机了, 接下来会做哪些事情

参考⽂档前⾯的章节 "第七章 哨兵 - 7.4 选举原理"

Redis 的集群是⼲什么的

参考⽂档前⾯章节 "第⼋章 集群"

Redis 的哈希槽是怎么回事

参考⽂档前⾯章节 "第⼋章 集群 - 8.2 数据分⽚算法"

Redis 集群的最⼤节点个数是多少

作者建议不要超过 1000 个.

参考链接:  https://github.com/antirez/redis/issues/2576

Redis 集群会有些操作丢失吗

Redis  并不能保证数据的强⼀致性,这意味这在实际中集群在特定的条件下可能会丢失写操作.

⽐如在写成功⼀个 key 之后, 正好主节点宕机, 此时由于这个数据还没有来得及同步到从节点上, 也没来得及 AOF 写⼊⽇志, 就丢失了.

Redis 集群如何选择数据库

Redis 集群不⽀持选择数据库. 只能使⽤默认的数据库 0 .

介绍下⼀致性哈希算法

参考⽂档前⾯章节 "第⼋章 集群 - 8.2 数据分⽚算法"

如何理解 Redis 的事务? 和 MySQL 的事务有啥区别?

参考⽂档前⾯章节 "第五章 事务"

Redis 和事务相关的命令有哪些

MULTI、EXEC、DISCARD、WATCH

为什么在⽣产环境上不应该使⽤ keys *  命令

keys *  类似于 sql 的  select *  , 如果存储的数据量特别⼤, 那么这个操作就会耗时⾮常⻓, 甚⾄阻塞住 Redis, 使 Redis 难以处理其他请求, 造成⽣产环境故障.

如何使⽤ Redis 作为消息队列

有三种典型的做法.

1)直接使⽤ List. Redis 中提供了 BLPOP 和 BRPOP, 可以阻塞式的获取元素. 就可以让消费者通过 List来进⾏阻塞式取元素, ⽣产者通过 RPUSH 或者 LPUSH 即可完成⽣产操作.

2)使⽤ PUB / SUB 命令.

3)使⽤ Redis 5 提供的 Stream 类型.

整体来说, Stream 这个⽅案提供的功能相对更加完整, 但是即使如此, 更多的时候还是使⽤专业的消息

队列更合适⼀些.

如果确实某个场景对于 MQ 的功能需求不⾼, 且不想引⼊额外的 mq 组件依赖, Redis 也可以使⽤.

如何使⽤ Redis 实现分布式锁

参考⽂档上⽅章节

什么是缓存穿透, 缓存雪崩, 缓存击穿

参考⽂档上⽅章节

什么是热 key 问题? 如何解决?

某些 key 的访问频率⾮常⾼. 称为 "热 key".

有些热 key 可能达到⾮常热的情况, 以⼀⼰之⼒就能把 redis 打挂.

💡虽然 Redis 通过集群部署的方式,能够分散请求的压力.

但是由于热 key 是同一个 key, 对应访问的机器也是同一组机器. 这就会导致其他组的机器虽然硬件资源富裕,但是也无法帮上忙.

如何解决:

  • 进⼀步扩⼤ Redis 集群的规模. 尤其是针对热 key 所属分⽚, 部署更多的 slave 节点分担读压⼒.
  • 应⽤服务器对热 key 识别出来, 并单独的进⾏⼆次哈希, 也就相当于是把⼀个 key 分散到多个 Redis分⽚上存储.
  • 应⽤服务器对热 key 识别出来, 把热 key 使⽤单独的 Redis 集群部署, 并赋予更多的机器.
  • 使⽤应⽤程序本地缓存, 降低 Redis 的压⼒.

如何实现 Redis ⾼可⽤

主从 + 哨兵 + 集群.参考⽂档上⽅章节.

Redis 和 MySQL 如何保证双写⼀致性

什么是 "双写⼀致性"

当⽤⼾修改数据的时候, 需要修改数据库, 同时也要更新缓存中的数据.

否则再直接读缓存的数据就是 "脏数据" 了.

但是如果直接写数据库并且写 Redis, 此时万⼀有⼀⽅写⼊失败, 就容易出现数据不⼀致的情况.

如何解决

⽅案⼀: 延时双删.

"双删" 的⽬的是多⼀重保证. 如果第⼀次删除失败, 第⼆次删除仍然能够兜底.

📌 只要把 Redis 的数据删了,后续访问该数据的时候就会自动的从数据库读取,并且把结果也写入 Redis 了. 就可以保证 Redis 和 数据库一致.

如果直接修改 Redis, 由于修改 Redis 和 修改 MySQL 并非是原子的,多个应用服务器并发执行的时候,可能就会出现类似于 "线程安全" 的问题了.

服务器1 和 服务器2 同时都写 Redis 和 MySQL,其中服务器1写 Redis 的结果被 服务器2 写Redis 的结果覆盖了. 服务器 2 写 MySQL 的结果被服务器 1 写 MySQL 的结果覆盖了. 此时就不一致了.

因此,"数据一致" 问题就转换成了能成功删除 Redis 数据的问题.

问题来了, 是否可能第⼆次删除也失败了呢?答案是肯定的. 但是概率是⼤⼤降低了.

⽅案⼆: 删除缓存重试

先删除缓存数据, 如果删除失败, 则把失败的 key 放到⼀个 mq 中, 稍后进⾏重试.

只要删除不成功, 这个重试就会反复⼀直进⾏.

上述操作确实能更严格的保证删除效果. 但是代码实现起来⽐较复杂.

幸运的是, 有⼤佬把这个过程封装好了, 我们可以直接使⽤.

例如 阿⾥巴巴 提供了开源⼯具 canal , 可以⽐较⽅便的获取到 mysql 的 binlog, 并基于此实现上述逻辑.

⽣成 RDB 期间, Redis 是否可以处理写请求

⽣成 RDB 有两种⽅式.

  • save. 这个操作会阻塞 Redis 的主线程, 此时⽆法处理外界的写请求.
  • bgsave. 这个操作会让 Redis ⽣成⼦进程. ⼦进程负责⽣成 RDB, ⽗进程负责处理写请求.

此时新写的数据不⼀定会被写⼊ RDB ⽂件中. 需要触发下⼀轮 RDB 的时候才能真正确保持久化了.

Redis 的常⽤管理命令有哪些

# dbsize 返回当前数据库 key 的数量。
# info 返回当前 redis 服务器状态和一些统计信息。
# monitor 实时监听并返回redis服务器接收到的所有请求信息。
# shutdown 把数据同步保存到磁盘上,并关闭redis服务。
# config get parameter 获取一个 redis 配置参数信息。(个别参数可能无法获取)
# config set parameter value 设置一个 redis 配置参数信息。(个别参数可能无法获取)
# debug object key 获取一个 key 的调试信息。
# debug segfault 制造一次服务器当机。
# flushdb 删除当前数据库中所有 key,此方法不会失败。小心慎用
# flushall 删除全部数据库中所有 key,此方法不会失败。小心慎用

Redis ⽤到的⽹络通讯协议是怎样的

Redis Serialization Protocol (RSP)

这个是 Redis 专⻔实现的应⽤层协议. ⽤于 Redis 客⼾端和服务器之间的通信.

RSP 是⼀种纯⽂本协议. 协议规则参考 https://redis.io/docs/reference/protocol-spec/

Redis 如何遍历 key

使⽤ keys * 虽然能⼀次性获取到所有 key,但是这个操作开销可能⾮常⼤, 会把 Redis 卡死.

更靠谱的⽅法是使⽤ scan 命令.

SCAN cursor [MATCH pattern] [COUNT count]

每次 scan 时间复杂度 O(1).

每次 scan 都能返回⼀批 keys 同时告知我们下次应该从哪⾥开始进⾏ scan

需要使⽤多次 scan 才能完成整个遍历.

Cursor 表⽰遍历 key 的光标. 从 0 开始, 每次执⾏ scan 都会返回下次开始的光标. 当返回结果为 0, 则说明遍历结束.

  通过 count 可以限制每次获取到的 key 的个数.

redis 127.0.0.1:6379> scan 0
1) "17"
2) 1) "key:12"2) "key:8"3) "key:4"4) "key:14"5) "key:16"6) "key:17"    7) "key:15"8) "key:10"9) "key:3"10) "key:7"11) "key:1"
redis 127.0.0.1:6379> scan 17
1) "0"
2) 1) "key:5"2) "key:18"3) "key:0"4) "key:2"5) "key:19"6) "key:13"7) "key:6"8) "key:9"9) "key:11"

🚅 Redis 是按照哈希 的方式来管理 keys 的,因此在遍历的时候得到的 keys 序列并非是 "有序"的.

每次调⽤ scan 会返回下⼀次 scan 的游标和本次的 keys.

下次再 scan 的时候根据这个游标继续遍历即可.

同理, 还提供了 hscan (哈希), sscan(set), zscan(zset), ⽤于遍历. ⽤法类似.

渐进式遍历解决了阻塞问题, 但是如果遍历过程中, 键存在变化, 则导致重复遍历或者遗漏.

Redis 如何实现 "查找附近的⼈" 

可以使⽤ Geospatial 类型, 存储每个⼈的地理位置.

geoadd key [经度] [纬度] member [经度] [纬度] member .......

使⽤

georadius key [经度] [纬度] [距离]

查询以给定位置为圆⼼, 距离为半径, ⾥⾯有哪些 member 符合条件.

什么是 Redis 的 "bigkey" 问题? 如何解决?

bigkey 指的是某个 key 对应的 value 占据较多的存储空间.

⽐如 value 是字符串类型, 是⼀个⾮常⻓的字符串; 或者 value 是 hash 或者 set 类型, ⾥⾯的元素特别多.

这样的 bigkey 会导致读写的时候性能下降. 如果是集群分⽚部署, 也会引起不同分⽚的数据倾斜.

解决⽅案:

核⼼思路就是拆分, 把⼀个⼤的 key 拆成多个⼩的 key, 每个 key 对应 value 的⼀部分数据.

可以使⽤ redis-cli --bigkey 查找 bigkey

删除 bigkey 不要直接使⽤ del, 也可能阻塞 Redis. 使⽤ unlink 命令在后台删除更合适.

redis%20%E6%BA%90%E7%A0%81" name="%E9%98%85%E8%AF%BB%20redis%20%E6%BA%90%E7%A0%81">阅读 redis 源码

阅读代码,核心思路 三个字 “花时间” 抓住一些问题. 针对性的看
1. redis 启动的过程是怎样的.
2. redis 是如何解析各种配置项的.
3. redis 是如何接收请求,并且处理请求命令的.
4. redis 持久化数据格式是怎样的(rdb,二进制格式如何生成的?).
5. 持久化触发实际在代码中具体怎么实现的.
6. 多线程具体起到什么作用.
看是一方面,整理是一方面=>形成一些 流程图/结构图

redis学习打卡🥳


http://www.ppmy.cn/embedded/158413.html

相关文章

React第二十八章(css modules)

css modules 什么是 css modules 因为 React 没有Vue的Scoped,但是React又是SPA(单页面应用),所以需要一种方式来解决css的样式冲突问题,也就是把每个组件的样式做成单独的作用域,实现样式隔离,而css modules就是一种…

LeetCode题练习与总结:最长和谐子序列--594

一、题目描述 和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。 给你一个整数数组 nums ,请你在所有可能的 子序列 中找到最长的和谐子序列的长度。 数组的 子序列 是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素…

Linux C++

一、引言 冯诺依曼架构是现代计算机系统的基础,它的提出为计算机的发展奠定了理论基础。在学习 C 和 Linux 系统时,理解冯诺依曼架构有助于我们更好地理解程序是如何在计算机中运行的,包括程序的存储、执行和资源管理。这对于编写高效、可靠的…

在线课堂小程序设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…

计算机毕业设计Python+CNN卷积神经网络小说推荐系统 K-means聚类推荐算法 深度学习 Kears 小说数据分析 可视化 Scrapy爬虫 协同过滤

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

智能调度体系与自动驾驶技术优化运输配送效率的研究——兼论开源AI智能名片2+1链动模式S2B2C商城小程序的应用潜力

摘要:随着全球化和数字化进程的加速,消费者需求日益呈现出碎片化和个性化的趋势,这对物流运输行业提出了前所未有的挑战。传统的物流调度体系与调度方式已难以满足当前复杂多变的物流需求,因此,物流企业必须积极引入大…

STM32标准库移植RT-Thread nano

STM32标准库移植RT-Thread Nano 哔哩哔哩教程链接:STM32F1标准库移植RT_Thread Nano 移植前的准备 stm32标准库的裸机代码(最好带有点灯和串口)RT-Thread Nano Pack自己的开发板 移植前的说明 本人是在读学生,正在学习阶段&a…

冬天适合养什么鱼?

各位鱼友们,冬天来了,是不是还在为养什么鱼而烦恼?别担心,今天就来给大家好好推荐一些适合冬天养的鱼,让你的水族箱在寒冷的冬天也能生机勃勃! 一、金鱼:冬日里的“小暖男” 金鱼绝对是冬季养鱼…