这是我参与「第五届青训营 」笔记创作活动的第17天
什么是redis
Redis基本工作原理Redis是一个基于BSD开源的项目,是一个把结构化的数据放在内存中的一个存储系统,你可以把它作为数据库,缓存和消息中间件来使用。同时支持strings,lists,hashes,sets,sorted sets,bitmaps,hyperloglogs和geospatial indexes等数据类型。它还内建了复制,lua脚本,LRU,事务等功能,通过redis sentinel实现高可用,通过redis cluster实现了自动分片。以及事务,发布/订阅,自动故障转移等等。
-
数据从内存中读写
-
数据保存到硬盘上防止重启数据丢失
- 增量数据保存到AOF文件
- 全量数据RDB文件
-
单线程处理所有操作命令
Redis那么快,除了单线程、基于内存等,还有它特殊的数据结构。
Redis应用实例
连续签到
- 在Redis中设置一个值,后天的0点过期
- String数据结构,sds,使用在存储计数、Session
消息通知
用list作为消息队列
-
使用场景:消息通知
-
List数据结构:Quicklist
- 由一个双向链表和listpack实现
计数
一个用户有多项计数需求,可通过hash结构存储
- Hash数据结构dict
- rehash:迁移某一个哈希节点下的值到另一个节点,数据量大时会阻塞用户请求
- 渐进式rehash:每次用户访问都迁移少量数据,平摊所有的迁移开销
排行榜
积分变化时,排名要实时变更
- zset数据结构,zskiplist跳表
- 结合dict后,可实现通过key操作跳表
限流
要求1秒内放行的请求为N,超过N禁止访问
利用当前时间戳构造一个key,对这个key调用incr,实现访问计数。
分布式锁
并发场景,要求一次只能有一个协程执行。执行完成后,其它等待中的协程才能执行。
可以使用redis的setnx实现,利用了两个特性
- Redis单线程执行命令
- setnx只有未设置过才能执行成功
但这并不是高可用的实现,因为可能会被超时的任务阻塞。
Redis使用注意事项
大Key,热Key
| 数据类型 | 大key标准 |
|---|---|
| String类型 | value的字节数大于10KB |
| Hash/Set/Zset/list等复杂数据结构类型 | 元素个数大于5000个或总value字节数大于10MB |
- 读取成本高
- 容易导致慢查询
- 主从复制异常,服务阻塞无法正常响应请求
消除大Key的方法:
集合类结构hash、list、set、set
(1)拆分:可以用hash取余、位掩码的方式决定放在哪个key中
(2)区分冷热:如榜单列表场景使用zset,只缓存前10页数据,后续数据走db
热Key的定义:
用户访问一个Key的QPS特别高,导致Server实例出现CPU负载突增或者不均的情况。热key没有明确的标准,QPS超过500就有可能被识别为热Key
解决热Key的方法
1.设置Localcache
在访问Redis前,在业务服务侧设置Localcache,降低访问Redis的QPS。LocalCache中缓存过期或未命中,则从Redis中将数据更新到LocalCache。Java的Guava、Golang的Bigcache就是这类LocalCache
⒉拆分
将keyvalue这一个热Key复制写入多份,例如key1:value,key2.value,访问的时候访问多个key,但value是同一个,以此将qps分散到不同实例上,降低负载。代价是,更新时需要更新多个key,存在数据短暂不一致的风险