5

Redis相关知识点的总结

 2 years ago
source link: https://discretetom.github.io/posts/redis-issues/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Redis概述

  • 内存k-v数据库,使用C语言编写,非常快,但是断电后内存中数据丢失(可以通过持久化数据避免数据丢失)
  • 通常用来做SQL数据库的缓存。也可以单独拿来做内存数据库,或者用来生成分布式唯一主键、实现分布式锁、队列等
  • 主进程是单线程的,所有数据操作都不会被并行处理。在执行持久化等操作的时候才会fork出子进程
  • 可以使用管道(pipe)实现简单的事务。也可以用来执行批量操作,提升操作速度

持久化方式

  • 默认位置:在启动redis服务端的目录中的dump.rdb
  • 使用二进制的形式保存内存中保存的数据
  • 触发方式
    • 手动触发
      • SAVE使用主进程进行持久化,会block操作
      • BGSAVE使用fork创建子进程进行持久化,主进程不受影响
    • 在Redis中执行SHUTDOWN时,如果没有配置AOF,则会触发持久化
    • 执行FLUSHALL时会触发,把RDB文件清空
    • 根据配置文件定时触发
      • 默认值
        • save 900 1 - 900秒内有1次写入时,保存
        • save 300 10 - 300秒内有10次写入时,保存
        • save 60 10000 - 60秒内有10000次写入时,保存
      • 如果开了主从配置,通常会关闭主节点的定时保存功能

Append-Only File

有点类似于时序数据库或MySQL的binlog。AOF文件会把写操作以字符串保存在文件中

  • 触发机制:编辑配置文件
    • no - 由操作系统触发,无法保证数据的持久化
    • always - 记录每一个写操作
    • everysec - 每秒保存一次。默认值。推荐
  • AOF重写:AOF文件过大时,合并AOF中的信息以减少AOF文件
    • 如果使用的redis版本较新,AOF文件可能会使用混合存储模式,使用RDB格式保存部分数据以进一步减少AOF文件大小(4.0版本引入混合存储,5.0版本默认使用混合存储)

使用默认配置的AOF,数据最多只会丢失2s,比RDB丢失的数据更少。

启动redis时,如果启动了AOF且目录下存在AOF文件则加载AOF文件。如果没有AOF文件且启动了RDB则加载RDB文件。如果都没有,则以空内容启动

Redis常见问题

大量缓存数据在同一时间失效,导致大量查询请求同时直接打到数据库

解决方案:

  • 使用随机TTL
  • 不使用TTL
  • 使用定时任务刷TTL

使用不合法参数,使缓存必定miss,从而直接把压力施加到数据库。比如数据库里面的id都是大于0的,使用小于0的id在redis里面查询必定会导致缓存miss,从而直接在数据库查询

解决方案:

  • 应用层参数验证、WAF
  • 封锁恶意用户IP
  • 使用布隆过滤器(Bloom Filter)

热点数据过期,会有大量请求直接打到数据库。比如电商秒杀场景

解决方案:

  • 不使用TTL
  • 如果是单体应用,可以使用分布式锁
    • 多个线程争夺一个互斥锁。拿到锁的线程负责访问数据库并更新到Redis,其他线程短暂sleep后重新访问Redis而不是数据库。这样就只会有一个请求打到数据库
  • leader/follower(master/slave)架构
    • 一个主库可以有多个从库(replica)
    • 从库可以有从库(sub-replica),形成级联架构
    • 从4.0开始,从库的从库会收到和从库一样的来自主库的指令流。所以即使向从库写数据,从库的从库也不会同步这些数据
  • 从库会试图维持和主库完全一致
  • 主库会向从库输出一个指令流(a stream of commands)
  • 连接断开时从库会主动尝试重连
    • 重连后会试图仅获取断开连接后丢失的指令流(部分同步,partial resynchronization)
    • 如果部分同步无法实现,从库会申请全量同步(full resynchronization)
      • 主库会对当前状态进行快照并发送给从库。然后继续同步指令流
  • 默认使用异步复制,从而保证低延迟、高性能。主库不会被阻塞
  • 可以对主库使用WAIT命令来等待复制完毕(触发同步复制)
  • 从库可以用来实现持久化,即主库不负责持久化,仅从库持久化
    • 这会有些危险:如果主库重启,主库是没有数据的,如果从库从主库同步数据,从库的数据也会丢失
  • 从库对主库使用PSYNC命令请求复制
    • 在从库的配置文件中写入replicaof <ip> <port>即可
    • 或者对从库执行REPLICAOF命令
    • 老版本的redis使用SYNC命令。它的协议比较老,且不支持部分同步
  • 只读副本
    • 从2.6开始,副本默认进入只读模式
    • 配置项:replica-read-only
    • 即使向副本中写数据,在进行主从同步时,向从库写入的数据也会丢失
  • 鉴权
    • 配置项masterauth <password>
  • 从库在NAT之后
    • 从库连接主库时会使用INFO命令/ROLE命令,这两个命令中包含从库的IP地址
    • 如果使用了NAT或者Docker之类的IP/端口映射,那么会导致请求IP和命令中的IP不符
    • 使用replica-announce-ip <ip>replica-announce-port <port>来解决

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK