这是我参与「第五届青训营」伴学笔记创作活动的第 17 天
为什么需要 Redis
- 数据分冷热
- 热数据 > 经常被访问的数据
- 将热数据存储至内存中, 避免高Qps下的性能问题
Redis 基本工作原理
- 数据在内存中读写
- 数据保存至硬盘上时防止重启数据丢失
- 增量备份 (AOF)
- 全量备份 (RDB)
- 单线程处理所有操作命令 (可以用于点赞等高并发操作)
应用案例
连续签到
比如 掘金 的每日签到, 用户每日签到一次,断签后计数归零。
- key: cc_uid_10001
- Value: 252 (签到天数)
- TTL: 后一天的0点
每次访问 执行 incr 1
消息通知
使用 list 作为消息队列 (Mq)
例如: 文章需要更新时, 将更新后的文章推送至 ElasticSearch, 此时用户就可以搜索到最新的文章数据。
List 作为一单向链表(先进先出). List 数据结构为 Quicklist.
计数
一个用户有多项技术计数时, 可以通过 hash
key: cc_uid_10001
| key | value | note |
|---|---|---|
| favo_count | 1 | 文章被点赞数 |
| followee_count | 1 | 关注数 |
| follower_count | 1 | 被关注数 |
Redis 相对于 Mysql, 将带来数十倍的读写速度。
可以使用 HincrBy 来 增加指定hash内的Key
排行榜
积分变化时,排名需要实时变更
- 结合 dict后 可通过 key 操作跳表功能
- ZINCRBY myzset 2 "Alex"
- ZSCORE myzset "Alex"
限流
- 要求 1秒内 放行的请求为 N, 超过 N 则禁止访问
Key: comment_freq_limit_{timestamp} 对此 Key 调用 incr, 超过限制 N 则禁止访问
分布式锁
并发场景,要求一次只能有一个协程执行。 执行完成后, 其他的协程才能执行。
可使用 redis 的 setnx 实现,利用其特性:
- redis 为单线程执行命令
- setnx 只有未设置才能执行成功
危害
大Key, 热Key
大key的危害:
- 读取成本高
- 容易导致慢查询
- 主从复制异常,服务阻塞
解决方案
- 拆分
将大Key 拆分为小key, 例如
| key | value | |
|---|---|---|
| 拆分前 | a_1 | ---- |
| 拆分后 | a_1_1 | [2][1]-- |
| a_1_2 | [1]-- |
- 压缩
使用 gzip,snappy, lz4 等算法进行压缩。
如果存储 json字符串, 可以使用 MessagePack 进行序列化。