TT Lab
开始
学习 学习路径 课程

Redis 与缓存

六种数据结构与各自的位置

在 TT Lab 中继续学习

一句话总结

使用Redis的好处不是知道很多命令,而是选择适合问题的数据结构。

为什么需要这个?

很多团队只用String写Redis,全部序列化为JSONSET做并且GET做。动作是做。但是即使只想更改用户资料的邮箱一个字段,也会读取整个内容,解析并修改后重新写入。同时,两个请求这样做的话,一方会覆盖另一个。

使用Hash的话HSET user:42 email a@b.com一条,不会与其他字段冲突。选择一个数据结构不满足竞争条件。

怎么行动

String是简单的值和计数器。INCR这个原子性这一点很重要——写在浏览量、延迟限制计数器、序列号上。SET key val NX EX 60是分散锁定的基本形式。

Hash是多个字段的对象。字段单位进行更新和查询,字段数量少时,Redis会使用内部压缩的编码,省去内存。

List是有序的列表,两端插入、删除是O(1)。写入工作队列和最近活动列表。中间访问是O(N),所以不能把大的列表作为索引。

Set是无重复的集合,交集、并集、差集是命令之一。用于标记、关注者、去重。SADD作为返回值,可以知道是“第一次看到吗”,也用于实现偏移性。

ZSet(排序集合)是具有分数的集合。始终保持按分数排序的状态,排名查询为O(log N)。写入排名、优先级队列、时间序列窗口(将分数作为时间戳)。在这个课程中,单独使用一个完整的练习非常重要。

Stream是额外的专用日志。有消费者群组和确认回复,真的离队列最近。在前道上都走了。

在现场相遇的样子

在运营中最要小心的是命令KEYS是。扫视整个kisspace,Redis这段时间不能做其他事情。因为Redis以单个线程处理命令,所以在键数百万的实例中KEYS *一次会造成数秒钟的全面停止。必须SCAN需要用光标旋转。

出于同样的理由FLUSHALL,关于大型收藏品的SMEMBERS/LRANGE 0 -1,DEL消除巨大的身高(相反UNLINK)也需要小心。"Redis突然变慢"的大部分原因都是一个O(N)命令。

也值得了解一下记忆的角度。MEMORY USAGE <key>可以查看按键实际使用量,即使是相同的数据,根据数据结构也会有几倍的差异。

决定选择什么的表格

数据结构 使用位置 代表命令 注意
String 缓存值,计数器 SET,INCR 512MB上限
Hash 对象的每个字段的更新 HSET,HGETALL 如果字段多的话HGETALL这个很重
List 库,最近N个 LPUSH,BRPOP 中间插入·查询为O(n)
Set 去重,标签 SADD,SINTER 大集合的交集很贵
Sorted Set 排名,按时间顺序索引 ZADD,ZRANGEBYSCORE 最有用
Stream 活动日志,消费者群组 XADD,XREADGROUP 比List更适合队列

Sorted Set 意外地被广泛使用。如果把分数作为时间戳,时间范围查询 成为(ZRANGEBYSCORE), 也容易删除旧的东西(ZREMRANGEBYSCORE). 如果想把“最近24小时内的活动”之类的东西做成List的话,很快就会被阻止。

Q比List更像Stream

用List创建队列的话BRPOP取出那一刻,信息就会消失。正在处理中 消费者死亡后,该信息将消失。

Stream有消费者群组和确认(ack)的概念。

XADD  orders * type payment amount 52000      # 발행
XREADGROUP GROUP workers w1 COUNT 10 STREAMS orders >   # 읽기(pending 으로 표시)
XACK  orders workers <id>                      # 처리 완료
XPENDING orders workers                        # 아직 확인 안 된 것
XCLAIM orders workers w2 60000 <id>            # 죽은 소비자의 것을 가져오기

XPENDING这就是核心。如果消费者死亡,该消息将留在pending中,其他 消费者XCLAIM带走。必须直接用List制作这个。

但是Stream也会无限增长XADD ... MAXLEN ~ 100000设置上限。 ~粘上的话可以很好地剪掉,所以更便宜。

大个子造成的问题

Redis以单个线程处理命令。如果一个花费很长时间,那么这段时间内全部 停止。

KEYS *                      → O(n). 절대 쓰지 않는다
HGETALL (필드 10만 개)      → 응답이 크고 오래 걸린다
SMEMBERS (원소 100만 개)    → 같은 문제
DEL (큰 컬렉션)             → 삭제도 O(n) 이다. UNLINK 를 쓴다

UNLINK将删除移至后台,避免阻止。删除大字体时,请使用这个。 写。

寻找大号钥匙是redis-cli --bigkeys我--memkeys是。定期返还 确认一个关键因素是否占了整体很大一部分。

下次实验要做的事情

逐一亲自处理六个数据结构,KEYS相反SCAN循环,最后将以相同的数据以不同的数据结构存储时的内存差异制成表格。