1. 简单地说一说 Redis 的主从。 主从是指一台 Redis 做 master,在 master 下面挂 n 个 slave,master 用来写数据,写完同步到 slave 上,slave 用来读数据。Redis 主从主要有两种种模式:
- 一主n从:一个 master 下面挂 n 个 slave,缺点就是这 n 个 slave 都是挂同一个 master 下,master 挂了从机还是从机,不会变成主机,那么这个主从也就不可用了,可以手动执行 slave of one 命令在 slave 中选出新的 master;
- 串联主从:A 下面挂着 B,B下面挂着 C,一脉相承;
2. Redis 主从复制的原理是什么?
- master 会生成一个 RDB 文件发送给 slave,slave 接收到 RDB 后先写入磁盘,然后再读取 RDB 同步数据。
3. Redis 集群有哪些方案?
- 哨兵:一主 n 从的自动版,上面说的 master 挂了需要手动选出新的 master,哨兵就是 Redis 会有一个 sentinel 集群去监控 Redis 的节点,一旦发现 master 挂了,就会投票选举出新的 master。优点就是简单易用,缺点就是只有一个 master 写数据,容易成为性能瓶颈。
- Redis-cluster:Redis 官方出的集群模式,它是有 n 个 master,每个 master下面挂 n 个 slave,也就是有 n 个主从。每个 master 之间不会同步数据,但是可以共享数据。写数据的时候,只会写到其中一个 master 上,然后会同步到这个 master 所属的 slave 上。读数据的时候,如果你是在没有那个 key 的节点上操作的,就会将命令转发到有那个 key 的节点上。由于要转发命令,每个 master 之间采用 gossip 协议进行通信,因此每个 master 都需要开放两个端口,比如一个是 6379, 那么还要一个加一万的 16379,用来进行通信。redis-cluster 的原理是,它采用了哈希槽的概念,总共有 16384 个哈希槽,然后将其分配给 Redis 的 master 节点,写数据时,用 crc16 算法对 key 进行计算,然后再对 16384 取余,就知道要写到哪个 master 上。这种方式优点就是性能好,支持动态扩容,缺点就是只能使用 0 号库,且不支持管道技术。
- 基于客户端分片:写数据的时候,在程序中就对 key 进行计算,判断好要写到哪个节点上。优点就是每个 Redis 实例之间没有关联,容易线性扩展,缺点就是 Redis 实例一旦增加,key 的映射规则就需要改。
- 基于代理分片:客户端请求都发到代理中,代理再去判断要发往哪台节点。优点是程序不需要关心有多少台 Redis 节点,不需要对 key 做映射规则,缺点就是多了一层代理,有性能损耗。常见的代理有豌豆荚开源的 codis 和推特开源的 Twemproxy。
4. 你是如何处理双写一致性问题的 双写一致性是指数据库数据与 Redis 中数据的一致性问题。一般是先写数据库,再写 Redis,不过这样会有问题,假如写完数据库,还没来得及更新 Redis 的时候,请求进来了,读取到的就是 Redis 中的旧数据。可以采用双删延迟策略来处理双写一致性问题。具体流程:
- 先删 Redis 中的数据;
- 然后更新数据库;
- 线程休眠一段时间;
- 再删 Redis 中的数据;
休眠一段时间再删的目的是,假如请求 A 进来先删了 Redis 中的数据,然后再还没来得及更新数据库的时候,请求 B 进来了,读取到的是数据库的旧数据;接着请求 A 更新完了 DB,再删 Redis;然后请求 B 再把读取到的旧数据写到 Redis 中,这样还是会导致数据库和 Redis 数据不一致。休眠一段时间就可以保证请求 B 能把读取数据库和写 Redis 的步骤执行完,执行完后请求 A 再去删 Redis,就可以把 Redis 中的旧数据删除。 所以休眠的时间应该大于请求 B 读数据库和写 Redis 的总时间。如果不是要求强一致性,不推荐这种做法,休眠一段时间体验不太好。
5. 如何处理并发竞争 key 的问题?
- 并发竞争 key 是指多个客户端同时对同一个 key 进行操作,可以用分布式锁,也可以用消息队列将请求变成串行的,或者写入的 value 值加个时间戳,写之前判断有没有晚与当前时间的时间戳存在,若有,则不写入。
6. 什么是缓存雪崩?如何解决?
- 缓存雪崩就是同一时刻缓存大面积失效,大量的请求直接落到数据库,把数据库压垮。解决办法是为 key 设置不同的过期时间,避免同一时刻失效,操作数据库的方法加锁,让请求串行。
7. 什么是缓存穿透?如何解决?
- 缓存穿透就是大量请求数据库和缓存中都没有的数据,造成数据库崩掉。解决办法是做好参数校验,非法请求直接挡掉;用布隆过滤器,将数据库的数据缓存到布隆过滤器中,请求数据库之前先判断布隆过滤器中有没有,没有就直接挡掉。
8. 什么是缓存击穿?如何解决?
- 缓存击穿就是同时大量请求 Redis 中没有的一个 key,所有这个 key 的请求都落到数据库,导致数据库崩掉。解决办法就是用布隆过滤器,设置热点数据永不过期等。
9. 如何在一亿个 key 中找出指定前缀的 key?
- keys prefix*:这种方式会阻塞 Redis,直至查询完成;
- scan 0 match prefix* count 10:利用游标,不会阻塞 Redis。这个就表示从 0 开始查询出 10 条符合条件的 key,第二次就是 scan 10 match prefix* 20。