# 配置

# 配置文件

  • 启动 Redis 服务器时,默认不会读取配置文件,而是采用软件的默认配置。

  • 可以将配置文件放在任意目录下,在启动 Redis 时采用配置文件,如下:

    redis-server /opt/redis/redis.conf
    
    • Redis 会读取该配置文件的内容,决定运行时的配置。
    • 每次修改配置文件之后,要重启 Redis 才会生效。
  • 配置文件示例:

    bind 0.0.0.0
    port 6379
    requirepass ******            # Redis 的密码。默认不启用密码认证
    # protected-mode yes          # 是否开启保护模式。如果开启了,但没设置 requirepass ,则会强制设置 bind 127.0.0.1
    
    dir /opt/redis/               # 工作目录,默认是 /var/lib/redis/
    # daemonize no                # 是否以 daemon 方式运行,默认为 no
    # pidfile /var/run/redis.pid
    # logfile ''                  # 日志文件的保存路径,默认是输出到 stdout
    # dbfilename dump.rdb         # 保存备份数据的文件名
    
    # databases 16                # 设置数据库的数量
    # maxclients 10000            # 限制客户端的连接数
    timeout 60                    # 当客户端连接的空闲时长超过 n 秒时,让 redis 断开该连接。默认禁用 timeout ,因此连接数会越来越多
    
    # 禁用掉一些不安全的命令
    rename-command FLUSHDB ""
    rename-command FLUSHALL ""
    rename-command KEYS ""
    

# 运行时配置

  • Redis 服务器启动之后,可以修改运行时的配置项。
  • 在客户端中,执行 config get/set <name> 可以查看、修改一个配置项。如下:
    127.0.0.1:6379> config get requirepass         # 查看密码
    1) "requirepass"
    2) ""                                          # 默认没有密码
    127.0.0.1:6379> config set requirepass 123456  # 设置密码
    OK
    
  • 执行 config get * 会显示所有配置项。
  • 执行 config rewrite 会将运行时的配置项保存到配置文件中,否则当 Redis 服务器终止时会丢失已修改的配置。

# ACL

  • Redis v6 增加了访问控制列表(ACL),可以定义多个用户,分配不同的权限。

    • 客户端登录时,需要输入用户名、密码进行认证。
      AUTH <username> <password>
      
    • 部署 Redis v6 时,默认会创建一个用户 default ,没有密码。这是为了向后兼容 Redis v5 客户端。
      • 当客户端登录时,如果不指定用户名,则会采用 default 用户。
      • 如果在 redis.conf 中配置 requirepass 123456 ,则会给 default 用户设置密码,相当于配置 user default on >123456
  • 常用的 ACL 命令:

    ACL USERS   # 列出所有用户名
    ACL LIST    # 列出所有用户名及其 ACL
    ACL WHOAMI  # 返回当前的用户名
    
    ACL DELUSER <user>
    ACL GETUSER <user>
    ACL SETUSER <user> [attribute]
    
    ACL CAT     # 查看 Redis 定义的 category
    
  • 例:查看当前的 ACL

    127.0.0.1:6379> acl list
    1) "user default on nopass ~* &* +@all"
    
    • user default 表示用户名为 default 。
    • on nopass 表示允许登录,并且无需密码。
      • 如果执行 acl setuser <user> off ,则禁止该用户登录,但不会关闭当前连接 Redis 的客户端。
      • 如果执行 acl setuser <user> resetpass ,则会清除密码、取消 nopass 。此时由于没有密码,该用户不能登录。
      • 如果执行 acl setuser <user> >****** ,则会给该用户添加一个密码,保存为 SHA-256 哈希值。
        • 可以重复执行该命令,给该用户添加多个密码。
    • ~ 开头的字段,表示允许访问哪些 key 。
      • 配置语法为 ~<pattern> ,这里的 pattern 采用 glob 匹配模式。
      • 例如 ~test_* 表示允许访问所有 test_ 开头的 key 。
      • 如果配置为 resetkeys ,则会清除已配置的规则。
      • Redis v7 中,
        • 可以配置为 %R~<pattern> ,表示允许读取与 pattern 匹配的所有 key 。
        • 可以配置为 %W~<pattern> ,表示允许写入。
        • 可以配置为 %RW~<pattern> ,表示允许读取+写入,相当于 ~<pattern>
    • & 开头的字段,表示允许访问哪些 channel 。
    • 最后一个字段,表示允许执行哪些 command 。
      • 可以用 +<command> 的格式,启用某个 command 。
      • 可以用 +@<category> 的格式,启用某个种类的所有 command 。
      • 将开头的 + 改成 - 则是禁用。
  • 例:查看 Redis 定义的 category

    127.0.0.1:6379> acl cat # 查看有哪些 category
    1) "keyspace"
    2) "read"
    3) "write"
    4) "set"
    ...
    127.0.0.1:6379> acl cat keyspace  # 查看某个 category 包含哪些 command
    1) "flushdb"
    2) "type"
    3) "persist"
    4) "rename"
    5) "dbsize"
    ...
    
  • 例:配置 ACL

    127.0.0.1:6379> acl setuser test  # 给用户 test 配置 acl 。如果该用户不存在,则自动创建它,此时默认禁止所有访问权限
    OK
    127.0.0.1:6379> acl list
    1) "user default on nopass ~* &* +@all"
    2) "user test off &* -@all"
    127.0.0.1:6379> acl setuser test ~test_*  # 可以多次执行 acl setuser ,这会增量修改 acl ,不会重置已有的 acl
    OK
    127.0.0.1:6379> acl setuser test ~public:*
    OK
    127.0.0.1:6379> acl list
    1) "user default on nopass ~* &* +@all"
    2) "user test off ~test_* ~public:* -@all"
    
    127.0.0.1:6379> acl setuser test reset  # 重置用户的 acl
    OK
    127.0.0.1:6379> acl list
    1) "user default on nopass ~* &* +@all"
    2) "user test off sanitize-payload &* -@all # sanitize-payload 表示密码的哈希值
    127.0.0.1:6379> acl setuser test >123456  # 添加一个密码
    OK
    127.0.0.1:6379> acl list
    1) "user default on nopass ~* &* +@all"
    2) "user test off sanitize-payload #8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 &* -@all"
    
  • 例:在 redis.conf 中持久化配置 ACL

    user default on >123456 ~* +@all
    user write   on >123456 ~* +@all -@dangerous
    user read    on >123456 ~* -@all +@read
    
    • 需要将每个用户的 acl ,配置在同一行,不支持多行增量修改。

# 备份

  • Redis 服务器将数据保存在内存中,当 Redis 终止时,内存中的数据都会丢失。
  • 可采用以下方案,持久化保存数据:

# RDB 模式

  • :如果在 n 秒内有至少 m 个 key 被改动,则将此时 Redis 的所有数据保存到备份文件中。
  • RDB 模式的备份开销小、备份精度低,但是恢复速度快。
  • Redis 默认启用 RDB 模式,相关配置如下:
    dbfilename dump.rdb   # 采用的备份文件的文件名
    
    # 默认采用以下备份策略
    save 3600 1           # 如果在 3600 秒内有 1 个 key 被改动,则备份一次
    save 300 100          # 在 300 秒内有 100 个 key 被改动
    save 60 10000         # 在 60 秒内有 10000 个 key 被改动
    
    # stop-writes-on-bgsave-error yes   # 当执行 bgsave 时,禁止写入数据
    # rdbcompression yes                # 是否压缩 RDB 备份文件
    
  • 可以执行以下命令,立即将数据保存到 dump.rdb 文件中:
    save      # 将所有数据保存到备份文件中(在前台执行)
    bgsave    # 在后台执行 save 命令
    

# AOF 模式

  • :将 Redis 执行的所有命令保存到备份文件中。
  • AOF 模式的备份精度高,但是备份开销大、恢复速度慢,因为要逐条执行命令。
  • 相关配置:
    appendonly yes                  # 是否启用 AOF 模式,默认禁用
    appendfilename appendonly.aof   # 采用的备份文件的文件名
    
    # 备份的策略
    # appendfsync always            # 每执行一条命令就保存一次,这是最慢、最安全的策略
    appendfsync everysec            # 每隔一秒保存一次,这是默认策略
    # appendfsync no                # 由 Redis 自己决定什么时候保存,间隔时间可能达几十秒
    
    # 自动重写 aof 文件
    # auto-aof-rewrite-min-size 67108864    # aof 文件考虑自动重写的最小体积
    # auto-aof-rewrite-percentage 100       # aof 文件超过最小体积时,每增大 100% 就重写一次
    
  • Redis 可以创建一个子进程,在后台重写 aof 文件,去掉重复、冗余的命令。
    • 每次重写时,会创建一个临时文件 temp-rewriteaof-xxx.aof ,重写成功了才用它替换 appendonly.aof 文件,因此重写失败也不会影响 appendonly.aof 文件。
    • 可执行 bgrewriteaof ,主动触发一次 aof 重写。
  • 采用 RDB 或 AOF 模式时,如果要恢复数据,只需将 dump.rdb 或 appendonly.aof 文件拷贝到 Redis 工作目录下,然后重启 Redis 。
    • Redis 启动时,默认会读取 dump.rdb 文件,将其中的数据载入内存。
      • dump.rdb 体积越大,则 Redis 启动耗时越久。例如使用机械硬盘时,从 dump.rdb 每加载 10GB 数据,耗时大概为 10s 。
      • 如果配置了 appendonly yes ,则 Redis 不会读取 dump.rdb ,而是读取 appendonly.aof ,逐一执行其中的命令。

# 混合模式

  • :在启用 AOF 模式做增量备份的基础上,每隔一段时间用 RDB 模式做一次全量备份。
  • 启用时,需要在 redis.conf 加入以下配置:
    appendonly yes
    aof-use-rdb-preamble yes  # 是否启用混合模式。从 Redis v5 开始默认为 yes
    
  • 混合模式下,会将数据备份到 appendonly.aof 文件,文件的前面部分存储 rdb 格式的数据,后面部分存储 aof 格式的数据。
    • 每次重写 aof 文件,都会将 aof 文件的内容全部重写为 rdb 格式。

# RedisShake

:一个命令行工具,用于将一个 Redis 的数据,同步到其它 Redis 。

  • GitHub (opens new window)
  • 由阿里云开源,采用 Golang 语言开发。
  • 有多种迁移数据的模式:
    • sync :基于 psync 命令从源 Redis 获取数据,然后导入目标 Redis 。这样属于增量同步。
    • restore :先导出源 Redis 的 dump.rdb 文件,然后从 rdb 文件中读取数据,导入目标 Redis 。这样属于全量同步。
    • scan :基于 scan 命令从源 Redis 获取数据,然后导入目标 Redis 。这样属于全量同步。
  • 用法:
    1. 下载 redis-shake 。
    2. 假设采用 scan 模式,修改配置文件 shake.toml :
      [scan_reader]
      cluster = false             # 是否为 cluster 模式
      address = "127.0.0.1:6379"  # 源 Redis 的地址
      username = ""
      password = "***"
      dbs = [1,2,3]               # 源 Redis 非 cluster 模式时,可以指定源 db
      
      [redis_writer]
      cluster = false
      address = "127.0.0.1:6379"  # 目标 Redis 的地址
      
      # 可选添加 lua 脚本,将数据过滤之后才导入目标 Redis
      # 下例是只同步指定 db 的数据,遇到其它 DB 则放弃执行
      function = """
      if DB ~= 0
      then
          shake.log("ignore source db=" .. DB)
          return
      end
      shake.log("write to db=" .. DB)
      shake.call(DB, ARGV)
      """
      
      [advanced]
      # 同步一个 key 时,如果目标 redis 已有同名的 key ,可采取以下对策
      # panic :让 redis-shake 报错 BUSYKEY 并停止同步
      # rewrite :覆盖已有的 key
      # skip    :跳过同步该 key
      rdb_restore_command_behavior = "panic"
      # 是否在开始同步之前,用 FLUSHALL 命令清空目标 redis
      empty_db_before_sync = false
      
    3. 执行以下命令,开始同步:
      ./redis-shake shake.toml
      

# 内存

  • 相关配置:
    maxmemory 1048576           # 限制 Redis 使用的最大内存,单位 bytes
    maxmemory-policy noeviction # 当 Redis 使用内存达到 maxmemory 限制时,采用什么对策
    
    • Redis 默认没有配置 maxmemory ,因此 Redis 可以无限占用内存。
      • 建议将 maxmemory 配置成主机内存的 80% 左右,留有一定冗余。
      • 当主机内存不足时, Redis 可能被 OOM 杀死。
    • 当 Redis 使用内存达到 maxmemory 限制时,可采用以下几种 maxmemory-policy 策略:
      noeviction        # 默认策略,不删除 key 。此时,如果用户写入 key ,则 Redis 会报错说达到 maxmemory 限制
      
      allkeys-lru       # 根据 LRU 算法,删除任意一个 key
      allkeys-random    # 随机删除一个 key
      
      volatile-ttl      # 删除 TTL 最短的 key
      volatile-lru      # 根据 LRU 算法,删除任意一个设置了 ttl 的 key
      volatile-random   # 随机删除一个设置了 ttl 的 key
      

# 慢日志

  • Redis 默认启用了慢日志。如果一个命令的执行耗时超过指定时长,则记录到慢日志。

    • 超过一定长度的命令会被截断。
  • 相关配置:

    slowlog-log-slower-than 10000 # 将超过指定耗时的命令记录到慢日志,单位为微秒 μs
    slowlog-max-len 128           # 最多记录多少条慢查询日志。达到限制时,删除最旧一条记录,写入新的记录
    
  • 相关命令:

    SLOWLOG GET [count] # 查看最近的 count 条记录,默认为 10 条
    SLOWLOG RESET       # 清空所有记录
    
    • 例:
      127.0.0.1:6379> SLOWLOG GET 1
      1)  1) (integer) 1099       # 这条慢日志的序号
          2) (integer) 1657077816 # 这条慢日志的记录时刻,格式为 Unix 时间戳
          3) (integer) 29212      # 命令的执行耗时,单位为微秒 μs
          4) 1) "KEYS"            # 命令的内容
            2) "hello*"
          5) "10.0.0.1:26869"     # 客户端地址
          6) ""                   # 客户端名称