Redis | 青训营笔记

66 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 10 天

Redis是什么

为什么需要redis

  • Mysql数据量增长,数据读写压力增长
  • 数据分冷热,将热数据存储到内存中

redis使用场景

读场景

先去redis中读,如果redis中找不到,再去mysql读,并写入redis

写场景

写入redis后,修改redis

Redis 基本工作原理

  • 数据从内在中读写
  • 支持AOF和RDB方式将数据持久化。每一条写命令会向AOF文件末尾加一条日志,重启服务时会重新执行AOF文件记录的命令。
  • 单线程处理所有操作命令

Redis的应用案例

连续签到

用户每日有一次签到机会,如果断签,连续签到计数器将归0,每天必须在23:59:59前签到。

  • Key: cc_uuid_1234565
  • value: 252
  • expireAt: 后天的0点

用户每次签到,将计数器加1,并把过期时间设置为后天0点

消息通知

用list作为消息队列:生产者将消息lpush进入队列左侧,消费者rpop从右侧消费消息。

当文章更新时,将更新后的文章推送到ES,用户就能搜索到最新的文章数据。

计数

维护用户的关注数、粉丝数、点赞数等数据。如果每次在数据库中count的话数据库压力很大。

一个用户有多项计数需求,可通过hash结构存储。

排行榜

积分变化时,排名要实时变更。使用zset数据类型,支持添加元素、排序输出。

限流

要求1秒内放行的请求为N,超过N则禁止访问

Key:时间戳

Value:计数器

每个请求让当前时间戳的计数器加1,计数器小于阈值则放行,大于阈值则禁止访问。

分布式锁

并发场景,要求一次只能有一个协程执行。执行完成后,其它等待中的协程才能执行。

可以使用redis的setnx实现,利用了两个特性:

  • Redis是单线程执行命令
  • setnx只有不存在才能执行成功。

Redis使用注意事项

大Key、热Key

大Key的定义

String value的字节数大于10kb

Hash/Set/Zset/list等元素个数大于5000个或总value字节数大于10MB

大Key的危害

  • 读取成本高
  • 容易导致慢查询
  • 主从复制异常,服务阻塞,无法正常响应请求

业务侧使用大Key的表现

  • 请求Redis超时

消除大Key的方法

  • 拆分:将大Key拆分为小Key,例如将一个string拆分成多个string
  • 压缩:gzip,snappy,lz4等
  • 集合类结构(hash,list,set,zset):拆分、区分冷热

热Key的定义

用户访问一个Key的QPS特别高,导致Server实例出现CPU负载突增或不均的情况。

解决热Key的方法

  • 设置Localcache
  • 拆分:将热Key复制写入多份
  • 使用Redis代理:实现热Key发现和LocalCache两个功能。

慢查询场景

容易导致redis慢查询的操作

  • 批量操作一次传入过多的元素
  • zset大部分命令时间复杂度是O(logn),数据量大时也可能导致慢查询
  • 操作的单个value过大
  • 对大key进行delete、expire等操作

缓存穿透、缓存雪崩

缓存穿透

热点数据查询绕过缓存,直接查询数据库

通常不会缓存不存在的数据,这类查询都会直接打到db,如果有系统bug或人为攻击,容易导致db反应慢甚至宕机

解决方法:缓存空值、布隆过滤器

缓存雪崩

大量缓存同时过期

同一时间大量key过期,也会导致大量请求落到db上

解决方法:分散过期时间、使用缓存集群