Redis学习记录 | 青训营

55 阅读5分钟

一、Redis是什么

为什么需要Redis?

数据库的演变:

  • 数据库表的衍生:从单表到分库分表。
  • MySQL从单机演进出集群,伴随而来的是数据量的增长和读写数据压力的不断增大。

数据的分类

  • 数据是分冷热的,热数据就是经常被访问到的数据,不妨将其存进内存中,可以增大读取速度,同时减少磁盘压力。
  • 当然内存中的数据是不持久的,重启后就会丢失。所以出现了Redis,其数据一定程度上可以做到持久化。
    • 怎么做到的呢?这涉及到Redis的基本工作原理:
      • 数据从内存中读写。
      • 数据保存到硬盘上防止重启丢失数据,通过RESP协议,及下面两种重要类型的文件:
        • 增量数据保存到AOF文件。
        • 全量数据RDB文件:启动Redis时会加载,并检查是否有命令未执行。
      • 单线程处理所有的操作命令:排队顺序处理,在数据同步、分布式锁等操作时会用到这个特性。
  • Redis的具体使用可以分为两个场景:
    • 读入场景:Web发送请求到服务端,服务端判断这是一个热数据还是冷数据,分别进到Redis或者MySQL里读取数据。
    • 写入场景:先写入MySQL,通过反解的BinLog反写Redis。

二、Redis应用案例

0. 先引入一个重要的数据结构:String sds

  • 可以存储字符串、数字、二进制数据,是二进制安全的。
  • 通常和expire配合使用。
  • 场景:存储计数、Session。

1. 连续签到

  • 场景:掘金有一个每日连续签到,每日有一次签到机会,若断签就会将计数归零。
  • 涉及到三个变量:Key(由用户ID等信息拼接),Value(连续签到的天数),Expireday(过期时间)。
  • 功能:Redis可以做到在某数据上增加1,及在指定的日期让数据过期。

2. 计数

  • Hash在Redis中是非常重要的数据结构。当一个用户有多项计数需求,可以通过hash结构存储。
  • 比如用户的文章总点赞数,因为是十分频繁访问的数据,如果存在SQL中,那么每增加一条点赞就要在表中增加一条数据,如此不但效率低下,还会使得磁盘IO的压力增大。
  • 更优的解决方法是使用哈希结构,将用户的id拼装成一个key,将所有的关于该用户的计数数据(点赞数、作品数、粉丝数等)存进这个hash结构里,不但读取快又能减少磁盘压力。另外,Hash本身自带给字段对应值增加的功能。
  • Pipeline:可以批量实现数据的增删改查。
  • 再额外介绍一下Hash这个数据结构:
    • rehash:由于Hash的拉链式结构,在某个槽位数据量过多时,要将该槽位的数据迁移到新的槽位,这样效率很低。
    • 渐进式rehash:每次用户访问时,都迁移少量数据,相当于将整个迁移过程平摊到所有的访问用不请求过程中。

3. 排行榜

  • 积分变化时,排名要实时更新。如果用如MySQL数据库用一个表实时维护排名信息,那么当用户数量级很高时,每次都要更新后重排序,十分不现实。
  • Redis中有一个zset结构能很好地解决这个需求。
  • zskiplist:跳表,将一条长链分成多条子链,加快查询速度。Redis中采用了跳表+hash两种数据结构的结合。一般跳表层数不超过4层。

4.分布式锁

  • 并发场景中,要求一次只能有一个协程执行,完成后其他等待的协程才能执行。比如限量商品的秒杀活动中要用到。
  • 可以利用Redis的setnx实现,利用了两个特性:
    • Redis的单线程执行命令
    • setnx只有未设置过才能执行成功
    • 更深入点来说,其实setnx不一定能保证。

三、Redis使用注意事项

1. 大Key和热Key

  • 大Key定义:
    • 对于String类型,当value字节数大于10kb
    • 对于Hash、Set、Zset、List等复杂数据结构:元素大于5000或总value字节数大于10MB
  • 危害:
    • 读取成本高
    • 导致慢查询(过期、删除)
    • 主从复制异常,服务阻塞, 无法正常相应请求
    • 业务侧中,容易造成请求Redis超时报错
  • 消除方法:
    • String结构:
      • 拆分:将一个大Key拆成小Key,比如一个String拆成多个String
      • 压缩:value压缩后再写入Redis,读取时先解压再使用。具体的压缩算法要根据实际情况选择。对Json字符串可以考虑MessagePack作序列化
    • 集合类结构:
      • 拆分:hash取余、位掩码方式决定放在哪个Key
      • 区分冷热
  • 热Key定义:
    • 用户访问一个Key的QPS特别高,导致Server实例出现CPU负载突增、不均。
    • 无明确定义,QPS超过500通常就会被认为是热Key
  • 消除方法:
    • Localcache:先从Redis中将数据更新到Localcache,即存到本机
    • 拆分:将一个热Key复制写入多份,分散到不同实例上

2.慢查询场景

  • 批量操作一次性传入过多key、value

3.缓存穿透、缓存雪崩

  • 前者指的是热点数据查询绕过了缓存,直接查询数据库
    • 比如查询一个一定不存在的数据,此时就会去查询数据库
  • 后者指大量的缓存同时过期
  • 前者可以缓存一个空值,对后者可以使用缓存集群。