Redis 之头裂攻略

1. 缓存介绍

问题 1: Redis 和 Memcache 的区别?如何选用?

Memcache

(1)Memcache 使用多线程异步 IO 的方式处理请求,充分利用 CPU 多核的优势;

(2)高性能,但节点压测性能能达到百万级的 QPS;

(3)功能简单,使用内存存储数据,只支持 KV 存储结构,不支持持久化和主从同步的功能;

(4)Memcache 淘汰 key 的策略

 

(5)限制:key 不能超过 250 个字节,value 不能超过 1 MB,key 的最大失效时间为 30 天;

Redis

(1)采用单线程处理请求

原因:

  • 采用非阻塞异步事件处理机制;
  • 所有数据都在内存中操作,时间不会太长
  • 单线程可以避免线程上下文切换开销

(2)支持持久化,所以 Redis 不仅可以用作缓存,也可以用来做 Nosql 数据库

(3)支持多种数据结构 String,Hash,Set,List,Sorted set 等

(4)提供主从同步的机制,cluster 集群的部署能力

问题 2:Redis 的数据结构及使用场景

(1)String:通过预分配冗余空间的方式来减少内存的频繁分配;

        使用场景:共享 Session,缓存热点数据

(2)List:由双向链表 LinkedList 和 压缩列表 ZipList 实现

ZipList:存储在一段连续的内存(类似数组),查询效率高,不利于数据修改操作

LinkedList:插入数据效率高,查询效率低,数据分散存储,容易产生内存碎片

3.2 版本后增加了 双向无环链表 QuickList:它的每个节点都是一个 ZipList

       使用场景:用作消息队列

(3)Hash:key 和 value 的大小都小于 64B,键值对数量小于 512 时,使用压缩表的存储结构,超过了 512 就转成哈希表

         使用场景:用于单独修改指定的用户属性,类似 Mysql 修改指定的字段值

(4)Set:由整数数组 IntSet 和 HashTable 实现,键值对数量小于 512 且数据都是数值类型时,使用整数数组的存储结构,超过了 512 就转成 HashTable

         使用场景:因为元素不会重复的特性,可用于求交集,找出共同好友

(5)Sorted Set:有序的集合,采用跳表 SkipList 和 压缩表 ZipList 实现,键值对数量小于 128 且长度小于 64 B时使用压缩表的存储结构,否则转成跳表

         使用场景:元素带有权重,可用于求一个游戏的用户得分榜

问题 3: Redis 有哪些持久化方式?区别是什么?

(1)RDB(内存快照,Redis 默认开启,适用于用做缓存):定时将内存中的所有数据都记录到磁盘中。RDB 记录的是某一时刻的数据,在数据恢复时,可以直接把 RDB 文件读入内存,很快地完成恢复。借助操作系统提供的写时复制技术,创建一个子线程去读取主线程的数据,并把它们写入 RDB 文件。

缺点:快照的频率不好把握,频率太低,两次快照间一旦宕机,就可能有比较多的数据丢失;太高又会产生额外的开销。

(2)AOF(Append Only File,性能差,不建议单独使用):将 Redis 的操作日志以追加的方式写入文件。Redis 先执行命令,然后把数据写入内存,然后才记录日志,不会阻塞当前的写操作。

存在风险:刚执行完一个命令,还没来得及记日志就宕机了。如果保存日志很慢,也会阻塞到后面的操作。相同数量的数据集,AOF 的文件通常要大于 RDB 文件,RDB 恢复数据的速度比 AOF 快。

三种写回策略:

  • Always 同步写回:每个写命令执行完,立马将日志写回磁盘
  • Everysec 每秒写回:先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区的内容写入磁盘(推荐)
  • No 操作系统控制写回:先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘

(3)RDB 和 AOF 混合使用

问题 4 :Redis 的过期机制是怎样的?

Redis 的过期策略是定期删除 + 惰性删除

定期删除:Redis 默认每隔 100 毫秒就会随机抽取带过期时间的 Key,检查其是否过期,然后删除。如果设置了过期时间的 Key 数量过多,每隔 100 毫秒就要进行一次检查,CPU 负载会非常高。定期删除会导致很多过期了的 Key 没有被删除。

惰性删除:获取 Key 的时候检查 Key 是否过期,过期就删除。没被获取的 Key 就无法进行检查和删除,导致内存堆积过多失效的 Key。

咋办呢? 按照淘汰策略淘汰 Key。

问题 5:Redis 有哪些淘汰策略?

(1)内存不足时,新的写入操作就会报错

(2)内存不足时,移除最近最少使用的 Key(LRU 算法)

(3)内存不足时,随机移除某一个 Key

(4)内存不足时,移除最近使用频率最低的 Key

问题 6:淘汰策略的算法

FIFO,LRU,LFU

问题 7:如何保证 Redis 的高并发和高可用?

依靠主从复制的架构

写:单机几万的 QPS

读:十万的 QPS

Redis 集群:几十万 的 QPS

问题 7:如何使用 Redis 实现延时队列?如何使用 Redis 实现分布式锁?

先拿 setnx 来争抢锁,抢到之后,再用 expire 给锁加一个过期时间防止锁忘记了释放。
如果在 setnx 之后执行 expire 之前进程意外 crash 或者要重启维护了,那会怎么样?
这个锁就永远得不到释放了,但是 set 指令有非常复杂的参数,这个可以同时把 setnx 和 expire 合成一条指令来用。
 

问题 8: 缓存常见问题

怎样保证数据最终一致性?

延时双删策略:更新数据库时同时删除缓存中的 Key,读的时候再填充缓存;或者 2 秒后再删除缓存中的 Key:或者设置 Key 的过期时间;将缓存删除失败的记录记录到日志中去,利用脚本提取失败记录,再次删除。通数据的 Binlog 异步淘汰 key,利用 Canal 将 Binglog 日志采集发送到 MQ 中,然后通过 ACK 机制确认处理要删除的 Key。

问题 9:单线程的 Redis 为什么这么快?

(1)Redis 的大部分操作在内存上完成,再加上它采用了高效的数据结构,例如哈希表和跳表;

(2)Redis 采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率;

(3)采用非阻塞异步事件处理机制;

(4)单线程避免了线程上下文切换的开销,没有并发访问锁控制问题;

(5)采用子线程处理持久化,不会阻塞主线程。

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页