关于Redis

五种数据类型:

String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)

性能优化:

使用批量操作来减少网络传输,减少RTT [往返时间](网络传输时间)

  • 原生批量操作命令 MGET、HMGET等、
    • 如 批量获取多个字符串键的值
      • 减少RTT时间
      • 原生实现、效率最高
      • 命令支持有限、Key数量有限
  • pipeline(流水线):将一批redis命令封装成一组然后一次性提交给服务器。
    • 十分通用,可以打包各种命令
    • 非原子性
    • 需要控制包(元素)的大小
  • Lua脚本:将多个命令写在一个 Lua 脚本中,然后将整个脚本作为一个字符串发送给 Redis 服务器。Redis 会单线程、原子性地执行整个脚本。
    • 原子性,但无法回滚,若程序异常中断,中断前的内容也会生效
    • 灵活性高,也可以实现较为复杂的逻辑
    • 有性能风险,编写的垃圾脚本可能导致堵塞线程
    • 主从复制Lua脚本可能会有压力

关于HotKey

  • 发现方法:
    • 用自带的 –hotkeys参数查找
    • 使用Monitor命令
    • 根据业务情况提前预估
  • 解决方法:
    • 拆分Key:
      • 一个 Key 的 Value 是一个包含 10000 个字段的 Hash,每次读取都传输整个 Value,则进行Key的拆分,将其拆分成 10 个 Hash,每个 Hash 包含 1000 个字段。
    • 读写分离:
      • 使用主从架构,将读请K求分散到多个从节点上。让应用程序将写请求发往主节点,而将大量的读请求发往一个或多个从节点。
    • 二级缓存:
      • 若热点Key:12345,则在L1本地缓存中缓存一份key:12345的数据。若未命中则查询L2(Redis)缓存 [ 这包含了本地缓存策略 ]

基于Redis实现延时任务

  • Redis过期事件监听:
    • 时效性差:
      • Redis采用的定时删除+惰性删除原则 会导致指定的过期时间到了但是Key还未被删除,进而没有发布过期事件的情况
      • 还有丢消息和消息重复的问题,都是Redis 的pub/sub模式固有的弊端
  • Redisson内置的延时队列

3种常用的缓存读写策略详解

  • Cache Aside Pattern (旁路缓存模式)
    • 适合读比较多的场景
    • 服务端需要同时维系db和cache
    • 写:先更新db,再更新cache
    • 读:从cache中读取数据,读取到就直接返回。
      • 读不到就从db读取。再把数据存入cache
        • 为什么是先更新数据库,再删除cache?
          • 若先删除cache,则在数据库更新前有请求访问cache,未命中,则直达数据库将旧数据写进缓存导致数据不一致
          • 若先更新缓存,如果数据库更新失败,则会导致缓存中的数据变成脏数据
          • 若先更新数据库,再更新缓存,则会导致在并发写的情况下,可能会出现线程A更新数据库后,线程B更新数据库,然后线程B更新缓存,最后线程A更新缓存的情况,导致缓存中是线程A的旧数据。
  • Read/Write Through Pattern (读写穿透)
    • 有性能问题,而且Redis没有提供将cache写入数据库的功能
  • Write Behind Pattern (异步缓存写入)
    • 有较强的数据不一致性问题

AOF持久化

1. 命令执行

  • 当 Redis 客户端执行一个写命令时(例如 SETHSETSADDDEL 等),服务器会在执行完该命令、将数据更新到内存中之后。
  • 将这个命令按照 Redis 序列化协议(RESP)的格式追加到服务器内存中的一个缓冲区(aof_buf)

关键点:先执行命令,再记录日志。这样做可以避免记录错误的命令,并且不会阻塞当前的写操作。但潜在风险是,如果命令执行成功但日志记录失败,可能会在宕机时丢失数据。

2. 日志追加AOF

  • 上一步中的 aof_buf 缓冲区存在于内存中,目的是为了将多次写命令集中起来,避免每次写命令都直接进行磁盘 I/O 操作,从而提升性能。

3. 文件同步/写入

  • Redis根据预先配置的策略,来决定何时将 aof_buf 缓冲区中的内容真正写入并同步到磁盘上的 AOF 文件
    • AOF 缓冲区根据对应的持久化方式( fsync 策略)向硬盘做同步操作。这一步需要调用 fsync 函数(系统调用), fsync 针对单个文件操作,对其进行强制硬盘同步,fsync 将阻塞直到写入磁盘完成后返回,保证了数据持久化。

4. 数据恢复 (Data Recovery)

  • 当 Redis 服务器重启时,如果需要使用 AOF 文件进行数据恢复,它会自动执行以下操作:
    1. 启动一个伪客户端
    2. 从头到尾读取 AOF 文件中的所有命令。
    3. 按顺序逐一重新执行这些命令,从而在内存中重建整个数据集。

Redis常见堵塞原因

  • O(n)命令:时间复杂度过大的命令可能导致堵塞,比如一些特定的KEYS *
  • 手动使用SAVE命令生成RDB快照文件
  • AOF日志记录阻塞(AOF日志记录是在主线程中进行的):
    • AOF日志记录是在当前命令组执行完毕后开始记录
      • 可以省略语法检查
      • 不会阻碍当前命令组的执行
    • 但是可能会阻止其他命令组的执行
  • AOF刷盘阻塞:当后台线程调用 fsync 函数同步 AOF 文件时,需要等待,直到写入完成。当磁盘压力太大的时候,会导致 fsync 操作发生阻塞
  • AOF重写阻塞:将缓冲区中新数据写到新文件的过程中可能会产生阻塞

Redis事务特性

  • 原子性:不具备原子性,因为不支持回滚因为开发者觉得没必要,命令错误应该在开发层面被发现
  • 持久性:支持,但是性能很差
    • 可以用Lua脚本保证原子性,但是Lua脚本要求代码命令不能有错,因为错误行前的代码都会被写入且执行
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇