/RedisRoute

redis学习路线

Primary LanguageJavaApache License 2.0Apache-2.0

RedisRoute

介绍

Redis学习路线 (37小时)

学习路线

  1. https://coding.imooc.com/class/151.html (作者:阿里redis开发规范)
  2. https://coding.imooc.com/class/467.html (从实战角度使用redis)

Redis特点

  1. 内存数据块,速度快,支持数据的持久化
  2. 支持数据备份(主从模式)以及集群分片存储,哨兵监控机制
  3. 支持事务
  4. Redis 是纯内存数据库
  5. Redis使用的非阻塞IO,IO多路复用,减少了线程切换时对上下文的切换和竞争
  6. Redis采用单线程模型,保证了操作原子性

Redis 基本数据类型

  1. 字符串(SDS)。采用预分配冗余空间的方式减少内存的频繁分配。最大为512M。应用场景,缓存,分布式锁。
  2. 散列。哈希表。用来存储对象信息。key->field:value。filed不能相同。有序。
  3. 列表。主要用于热搜榜单,Feed流。支持重复元素。无序。
  4. 集合。主要具备并集,交集,差集的功能。不支持插入重复元素。
  5. 有序集合。根据权重进行排序,比如游戏积分榜,设置优先级任务列表,学生成绩等。
  6. 位图。内部是使用字符串实现的。操作bit
  7. HyperLogLog。存在误差,无法取出存储数据。
  8. GEO 地理信息定位

Redis主要应用场景

  1. 缓存系统
  2. 计数器
  3. 排行榜
  4. 实时系统
  5. 消息队列系统
  6. 社交系统

Redis其他功能

  1. 慢查询
    1. 先进先出队列
    2. 固定长度
    3. 保存在内存中
    4. 配置
      1. slowlog-max-len。 默认值 128
      2. slowlog-log-slower-than .默认值 10000
    5. 定期持久化慢查询
  2. pipeline流水线
    1. pipline每次条数要控制
    2. 非原子性 操作
  3. 发布订阅
    1. 无法消息堆积,获取历史消息

Redis持久化

  1. 持久化概念:将内存数据保存到磁盘
  2. 持久化方式
    1. RDB。快照。
      1. 触发方式
        1. save 同步 阻塞。替换旧的RDB文件。
        2. bgsave 异步。fork进程
        3. 自动
        4. 主从复制
        5. debug reload
        6. shutdown
      2. 问题点
        1. 耗时,耗性能
        2. 不可控,容易丢失数据
    2. AOF。写日志。
      1. 触发方式
        1. always
        2. everysec
        3. no
      2. AOF重写
        1. 减少磁盘占用
        2. 加快恢复速度
    3. RDB与AOF的比较

Redis主从复制

  1. 作用
    1. 数据副本
    2. 扩展读性能
  2. 实现方式
    1. slaveof命令
    2. 配置方式

Redis哨兵模式

  1. 三个定时任务
    1. 每10每个sentinel对master 和slave进行info
      1. 发现slave节点
      2. 确认主从关系
    2. 每2秒每个sentinel通过对master节点的channel交换信息
      1. 通过_sentinel_:hello 频道交互
      2. 交互对节点的看法和自身信息
    3. 每1秒每个sentinel 对其他sentinel 和 redis 执行ping.
  2. 主观下线和客观下线
    1. 主观下线:每个sentinel节点对redis节点失败的偏见
    2. 客观下线:所有sentinel节点对redis节点失败达成共识
  3. 领导者选举
    1. 选举通过sentinel is-master-down-by-addr命令都希望成为领导者
  4. 故障转移
    1. 从slave节点选出一个合适的节点作为新的master节点
    2. 对上面的slave节点执行 slave of no one 命令 让其成为master节点
    3. 向剩余的slave节点发送命令,让它们成为新master节点的slave节点,复制规则和parallel-sync参数有关
    4. 更新对原来master节点配置为slave,并保持对其的关注,当其恢复后命令它去复制新的master节点
  5. 注意点
    1. 客户端初始化连接的Sentinel节点集合,不再是具体的redis节点,但sentinel只是配置中心不是代理。

Redis 避坑指南

  • 怎么正确的选择数据类型。
    1. 所有的数据都可以使用string去表示
    2. 都使用string去存储数据存在以下弊端
      1. 浪费存储空间,key也需要存储空间的
      2. 管理维护麻烦,Redis中存在大量的KV对象
      3. key冲突的几率变高(不同业务系统共用一个Redis服务)
    3. key的命令策略(建议)(业务线名称+ 工程名+ 模块名+有意义的键名)
      1. 同一个Redis服务被公司中的各个业务线共用
    4. 常用的数据类型及其适用场景
      1. string : 应用最为广泛的数据类型:例如:计数器,session等键值
      2. hash : 存储结构化(对象的)数据,KV共同构成一个对象的信息
      3. list : 队列、栈、有界队列
      4. set : 去重、无序的数据结合。在类似于社交的业务功能上有引用。比如共同关注、共同喜好、数据去重
      5. sortedset:带有权重的集合,在类似于排行榜业务上有广泛应用,且可以实现范围查找
  • 使用了事务功能,为何没回滚
    1. Redis事务:四个指令。MULTI :开启。EXEC :启动。DISCARD: 废弃。WATCH :观察
    2. 事务可以一次执行多个命令,并且可以进行单独的隔离操作,原子操作。
    3. Redis事务的两类错误
      1. 事务在执行EXEC之前,入队的命令出错。原因: 命令语法错误。服务器内存不足。
        1. Redis拒绝执行,自动放弃这个事务。
      2. 命令在EXEC调用之后失败。原因:命令语法错误
        1. 事务队列中的其他命令会继续执行,事务不会停止。
    4. Redis不支持回滚
      1. Redis命令只会因为错误的语法而失败,或者命令用了错误类型的键上面
      2. 因为不需要对回滚进行支持,所以Redis内容可以保持简单且快速
  • Redis 性能上不去,可能有big key
    1. Big key 以及造成的伤害(数据量大的key,比如字符串value值非常大(>10KB),哈希、列表、集合、有序集合元素多(个数>5000))
      1. 内存不均
      2. 超时阻塞
      3. 网络流量拥塞
      4. 过期删除
      5. 迁移困难
    2. Big key 怎么产生的
    3. 社交类场景:典型的是粉丝列表,对于大V来说,需要特殊统计,否则就成为了big key
    4. 汇总统计类场景: 每天都会产生报表数据,报表数据汇总到一个key里,日积月累就成为了big key
    5. 日常缓存类场景:对DB中的数据进行缓存,大表很可能会产生big key
    6. 发现big key
    7. redis-cli 提供 --bigkey来查找bigkey ;给出了每种数据结构的top1 bigkey。同时给出每种数据类型的键值个数以及平均大小
    8. Redis 4.0开始提供memory usage 们能够令可以计算每个键值的字节数
    9. 删除big key ,不要贸然行动
    10. string : 可以直接使用del 命令,不会产生阻塞
    11. dict :使用hscan 命令每次获取部分field-value,再使用hdel删除每个field
    12. set :使用scan命令,每次获取部分元素哦,再使用srem命令删除每个元素
    13. sortedset : 使用zscan命令,每次获取部分元素,再使用zremrangebyrank命令删除元素
  • Redis 内存耗尽
    1. 原因
      1. 业务不断发展,缓存数据不断增多,需要消耗Redisn内存
      2. 无效的(过期的)数据没有及时清理,需要消耗Redisn内存
      3. 没有对冷数据进行降级,需要消耗Redis内存
    2. 使用EXPIRE命令将KEY标记为Volatile的
      1. 使用EXPIRE命令给key设置生存时间,当key过期时,它会被自动删除
      2. 如果一个命令只是修改一个带生存时间的key的值而不是用一个新的key来代替它的,那么生存时间不会被改变
      3. 如果PERSIST 命令可以在不删除KEY情况下,移除KEY的生存时间,让key重新成为一个持久的key
      4. 可以对一个已经带有生存时间的key执行EXPIRE命令,所指定的生存时间会带旧的生存时间
    3. Redis删除策略
      1. 定时删除: 对于每一个设置过期时间的key,都会创建一个定时器,一旦到达过期时间就立即删除
      2. 惰性删除:当访问一个key时,才判断该key是否过期,过期则删除
      3. 定期删除:每隔一段时间,扫描Redis中过期key字典,并清除部分过期的key
  • 有了过期机制以后内存还不够用怎么办
    • Redis内存的淘汰策略
      1. Redis内存的淘汰策略,是指内存达到maxmeory极限时,使用某种算法来决定清理掉哪些数据,以保证新数据的存入
    • Redis的内存淘汰机制(volatile策略只会针对带过期时间的key进行淘汰,allkeys策略会对所有的key进行淘汰)
      1. noeviciton
      2. allkeys-lru
      3. allkeys-random
      4. volatile-lru
      5. volatile-random
      6. volatile-ttl
    • 配置Redis:redis.confg。 maxmeory:1024000
    • 策略选择
      1. 如果只是拿Redis做缓存,那应用使用allkeys下的淘汰策略
      2. 如果还同时使用Redis的持久化功能,那就是用volatile下的淘汰策略
  • 如何解决频繁的命令往返造成的性能瓶颈
    • Redis 客户端与服务端的交互模型
      1. Redis 是基于一个Request ,一个Response的同步请求服务
      2. 数据包往返于两端的时间被称之谓RTT
    • 解决方案 :使用pipline
    • Redis pipeline 与原生批量命令对比
      1. 原生批量命令是原子性,pipline是非原子性的
      2. 原生批量命令一次只能一种命令,pipline支持批量执行不同命令
      3. 原生批量命令是服务端实现,而pipline需要服务端与客户端共同完成。
    • 使用pipline的注意点:
      1. 使用pipline组装的命令个数不能太多,不然数据量过大
      2. pipline会按照指令缓存的顺序执行,但可能会穿插其他客户端发送来的命令,即时序性不一定能保证
      3. pipline执行中间某一个指令出现异常,将会继续执行后续的指令,既不能保证原子性。
  • Redis 持久化
    • 为什么需要持久化
      1. 高并发场景只是用Redis作为存储设备,需要保证数据不会丢失
      2. 通常应用场景虽然会同时把数据写入mysql,但是直接从mysql中恢复数据性能低下,且缺失选择性
    • RDB的持久化配置
      1. save : 时间策略
      2. dbfilename : 文件名称
      3. dir : 文件保存路径
      4. stop-writes-on-bgsvae-error:如果持久化出国,主进程是否停止写入
      5. rdbcompression:是否压缩
      6. rdbchecksum:导入时是否检查
    • 触发原理
      1. 手动触发
        1. save会阻塞当前Redis服务器。直到持久化完成,线上应该禁止
        2. bgsave:该触发方式会fork一个子进程,由紫禁城负责持久化,因此只会阻塞发生在fork子进程的时候
      2. 定时触发
        1. 根据我们的save m n 配置规定自动触发
        2. 从节点全量复制时,主节点发送rdb文件从节点完成复制操作,主节点会触发bgsave
        3. 执行shutdown时,如果没有开启aof,也会触发
    • AOF的持久化配置
      1. appendonly: 是否开启aof
      2. appendfilename : 文件名称
      3. appendfsync:同步方式
      4. no-appendfsync-on-rewrite:aof重写期间是否同步
      5. aof-load-truncated:加载aof时,如果有错如何处理
    • AOF 重写
      1. 当AOF文件的大小超过所设定的阀值时,Redis就会自动启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集
      2. 触发机制:Redis会记录上次重写时的AOF的大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64MB时触发
      3. 重写原理:将整个内存中的数据库内容用命令的方式重写一个新的AOF文件,这点和快照有点类似
    • 恢复方式
      1. 存在AOF 加载AOF
      2. 不存在AOF 加载RDB
      3. 都不存在,启动失败
  • 缓存穿透的隐患
    • 缓存穿透
      1. 概念:查询一个一定不存在的数据,如果规则是从数据库中查不到数据不写入缓存,这将导致这个不存在的数据每次请求都要到数据库中查询
    • 缓存穿透的解决方案
      1. 缓存预热:系统上线后,提前将相关的缓存数据直接加载到缓存系统
        1. 如果查询数据库也为空,直接设置一个默认值存放到缓存,第二次就到缓冲中就有值了,而不会继续访问数据库
      2. 在数据处理层,进行数据校验,判断数据类型和数据范围
      3. 使用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个不存在的数据会被这个bitmap拦截掉
  • 缓存雪崩
    • 缓存雪崩带来的问题
      1. 瞬时请求都会被转发到mysql上,给后端数据库造成瞬时的负载升高的压力
      2. 如果请求量增多,并发度高,可能会使mysql压力过大而导致系统宕机
    • 解决方案
      1. 过期时间错开(可以在一个基础时间上增减一个随机值),避免热点数据集中失效
      2. 本地缓存+ hystrix限流&降级,避免数据库访问压力过大