【redis进阶】redis 总结

目录

介绍一下什么是 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 源码


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 源码

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

redis学习打卡🥳

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/962120.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI大模型开发原理篇-1:语言模型雏形之N-Gram模型

N-Gram模型概念 N-Gram模型是一种基于统计的语言模型,用于预测文本中某个词语的出现概率。它通过分析一个词语序列中前面N-1个词的出现频率来预测下一个词的出现。具体来说,N-Gram模型通过将文本切分为长度为N的词序列来进行建模。 注意:这…

Linux工具使用

1.gcc/g的使用 1.1程序翻译的过程 ①预处理:展开头文件,替换宏,调节编译,去注释。 ②编译:将代码变成汇编语言 ③汇编:将汇编代码变成二进制不可执行的目标文件。 ④链接:将多个我写的多个…

后端token校验流程

获取用户信息 前端中只有 await userStore.getInfo() 表示从后端获取数据 在页面中找到info对应的url地址,在IDEA中查找 这里是getInfo函数的声明,我们要找到这个函数的使用,所以点getInfo() Override public JSONObject getInfo() {JSO…

Python 梯度下降法(二):RMSProp Optimize

文章目录 Python 梯度下降法(二):RMSProp Optimize一、数学原理1.1 介绍1.2 公式 二、代码实现2.1 函数代码2.2 总代码 三、代码优化3.1 存在问题3.2 收敛判断3.3 函数代码3.4 总代码 四、优缺点4.1 优点4.2 缺点 Python 梯度下降法&#xff…

excel如何查找一个表的数据在另外一个表是否存在

比如“Sheet1”有“张三”、“李四”“王五”三个人的数据,“Sheet2”只有“张三”、“李四”的数据。我们通过修改“Sheet1”的“民族”或者其他空的列,修改为“Sheet2”的某一列。这样修改后筛选这个修改的列为空的或者为出错的,就能找到两…

2024年数据记录

笔者注册时间超过98.06%的用户 CSDN 原力是衡量一个用户在 CSDN 的贡献和影响力的系统,笔者原力值超过99.99%的用户 其他年度数据

7层还是4层?网络模型又为什么要分层?

~犬📰余~ “我欲贱而贵,愚而智,贫而富,可乎? 曰:其唯学乎” 一、为什么要分层 \quad 网络通信的复杂性促使我们需要一种分层的方法来理解和管理网络。就像建筑一样,我们不会把所有功能都混在一起…

JxBrowser 8.2.2 版本发布啦!

JxBrowser 8.2.2 版本发布啦! • 已更新 #Chromium 至更新版本 • 实施了多项质量改进 🔗 点击此处了解更多详情。 🆓 获取 30 天免费试用。

论文阅读(十五):DNA甲基化水平分析的潜变量模型

1.论文链接:Latent Variable Models for Analyzing DNA Methylation 摘要: 脱氧核糖核酸(DNA)甲基化与细胞分化密切相关。例如,已经观察到肿瘤细胞中的DNA甲基化编码关于肿瘤的表型信息。因此,通过研究DNA…

【综合决策模型】考虑生命周期评估LCA 与多目标优化MOO的综合决策模型MOOLCA

目录 1. 概念和目的1.1 生命周期评估 (LCA, Life Cycle Assessment)1.2 多目标优化 (MOO, Multi-Objective Optimization)1.3 MOOLCA 的目标2. MOOLCA 的组成2.1 生命周期评估模块2.2 优化模块2.3 决策支持模块参考Life Cycle Assessment with Multi-Objective Optimization (M…

系统思考—蝴蝶效应

“个体行为的微小差异,可能在系统中引发巨大且不可预测的结果。” — 诺贝尔经济学得主托马斯谢林 我们常说,小变动带来大影响,这种现象,在复杂系统理论中被称为“蝴蝶效应”:即使极小的变化,也能在动态系…

设计模式Python版 适配器模式

文章目录 前言一、适配器模式二、适配器模式实现三、适配器模式在Django中的应用 前言 GOF设计模式分三大类: 创建型模式:关注对象的创建过程,包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。结构型模式&…

科研绘图系列:R语言绘制散点图(scatter plot)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据画图保存图片系统信息参考介绍 科研绘图系列:R语言绘制散点图(scatter plot) 加载R包 library(tidyverse) library(ggthemes) library(ggpubr) libr…

基于单片机的超声波液位检测系统(论文+源码)

1总体设计 本课题为基于单片机的超声波液位检测系统的设计,系统的结构框图如图2.1所示。其中包括了按键模块,温度检测模块,超声波液位检测模块,显示模块,蜂鸣器等器件设备。其中,采用STC89C52单片机作为主控…

P1044 [NOIP2003 普及组] 栈 C语言

P1044 [NOIP2003 普及组] 栈 - 洛谷 | 计算机科学教育新生态 题目背景 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表。 栈有两种最重要的操作,即 pop(从栈顶弹出一个元素)和 pus…

基础项目实战——学生管理系统(c++)

目录 前言一、功能菜单界面二、类与结构体的实现三、录入学生信息四、删除学生信息五、更改学生信息六、查找学生信息七、统计学生人数八、保存学生信息九、读取学生信息十、打印所有学生信息十一、退出系统十二、文件拆分结语 前言 这一期我们来一起学习我们在大学做过的课程…

OpenEuler学习笔记(十七):OpenEuler搭建Redis高可用生产环境

在OpenEuler上搭建Redis高可用生产环境,通常可以采用Redis Sentinel或Redis Cluster两种方式,以下分别介绍两种方式的搭建步骤: 基于Redis Sentinel的高可用环境搭建 安装Redis 配置软件源:可以使用OpenEuler的默认软件源&#…

Python的那些事第六篇:从定义到应用,Python函数的奥秘

新月人物传记:人物传记之新月篇-CSDN博客 目录 一、函数的定义与调用 二、函数的参数 三、返回值(return语句) 四、作用域 五、匿名函数(lambda表达式) 六、总结 Python函数的奥秘:从定义到应用 编程…

vue3的路由配置

先找到Layout布局文件&#xff0c;从中找到左侧边栏&#xff0c;找到下述代码 <SidebarItem v-for"route in noHiddenRoutes" :key"route.path" :item"route" :base-path"route.path" />/** *菜单项 <SidebarItem>: *使用…

VLLM性能调优

1. 抢占 显存不够的时候&#xff0c;某些request会被抢占。其KV cache被清除&#xff0c;腾退给其他request&#xff0c;下次调度到它&#xff0c;重新计算KV cache。 报这条消息&#xff0c;说明已被抢占&#xff1a; WARNING 05-09 00:49:33 scheduler.py:1057 Sequence gr…