START

Basic

Redis 和 Memcached 有什么区别?

Back:

Redis 与 Memcached 区别

START

Basic

五种常见的 Redis 数据类型是怎么实现的?

Back:

image.png

END

START

Basic

Redis 的单线程模型?

Back:

Redis 单线程指的是「接收客户端请求->解析请求 ->进行数据读写等操作->发送数据给客户端」这个过程是由一个线程(主线程)来完成的,这也是我们常说 Redis 是单线程的原因。

但是,Redis 程序并不是单线程的,Redis 在启动的时候,是会启动后台线程(BIO)的

之所以 Redis 采用单线程(网络 I/O 和执行命令)那么快,有如下几个原因:

START

Basic

Redis 如何实现数据不丢失?

Back:

Redis 共有三种数据持久化的方式:

START

Basic

Redis 使用的过期删除策略是什么?

Back:

当我们查询一个 key 时,Redis 首先检查该 key 是否存在于过期字典中:

Redis 使用的过期删除策略是「惰性删除+定期删除」这两种策略配和使用。

END

START

Basic

Redis 是怎么实现 LRU 的

Back:

Redis 实现的是一种近似 LRU 算法,目的是为了更好的节约内存,它的实现方式是在 Redis 的对象结构体中添加一个额外的字段,用于记录此数据的最后一次访问时间

当 Redis 进行内存淘汰时,会使用随机采样的方式来淘汰数据,它是随机取 5 个值(此值可配置),然后淘汰最久没有使用的那个

Redis 实现的 LRU 算法的优点:

START

Basic

Redis 如何避免缓存雪崩、缓存击穿、缓存穿透?

Back:

通常会给缓存中的数据项设置过期时间,过期时间一到无论如何都要去存储层取数据,如果过期时间过于相近,就会在某一个时刻同时出现大量缓存失效,这就是缓存雪崩

我们可以将过期时间打散来解决缓存雪崩的问题

缓存击穿是指某一热点数据的缓存失效了,无法从缓存中读取,直接访问数据库,数据库很容易就被高并发的请求冲垮

缓存穿透是指大量访问既不在缓存,也不在数据库中的数据项,也会引起频繁的数据库访问

START

Basic

Redis 是否支持事物回滚?

Back:

Redis 中并没有提供回滚机制,虽然 Redis 提供了 DISCARD 命令,但是这个命令只能用来主动放弃事务执行,把暂存的命令队列清空,起不到回滚的效果,事务中执行时的错误会被忽略,但是正常执行了的语句无法回滚。

END

START

Basic

Redis 如何实现分布式锁?

Back:

Redis 的 SET 命令有个 NX 参数可以实现「key不存在才插入」,所以可以用它来实现分布式锁:

START

Basic

Redis 如何解决集群情况下分布式锁的可靠性?

Back:

Redis 主从复制模式中的数据是异步复制的,这样导致分布式锁的不可靠性。如果在 Redis 主节点获取到锁后,在没有同步到其他节点时,Redis 主节点宕机了,此时新的 Redis 主节点依然可以获取锁,所以多个应用服务就可以同时获取到锁。

为了保证集群环境下分布式锁的可靠性,Redis 官方已经设计了一个分布式锁算法 Redlock(红锁)。

Redlock 算法的基本思路,是让客户端和多个独立的 Redis 节点依次请求申请加锁,如果客户端能够和半数以上的节点成功地完成加锁操作,那么我们就认为,客户端成功地获得分布式锁,否则加锁失败

Redlock 算法加锁三个过程(需要在锁过期的时间内获取到超半数的 Redis 节点上的锁):

START

Basic

Redis 大 key 对系统的影响

Back:

当 AOF 写回策略配置了 Always 策略,如果写入是一个大 Key,主线程在执行 fsync() 函数的时候,阻塞的时间会比较久,因为当写入的数据量很大的时候,数据同步到硬盘这个过程是很耗时的。

AOF 重写机制和 RDB 快照(bgsave 命令)的过程,都会分别通过 fork() 函数创建一个子进程来处理任务。会有两个阶段会导致阻塞父进程(主线程):

大 key 除了会影响持久化之外,还会有以下的影响:

如何避免大 Key 呢?

最好在设计阶段,就把大 key 拆分成一个一个小 key。或者,定时检查 Redis 是否存在大 key ,如果该大 key 是可以删除的,不要使用 DEL 命令删除,因为该命令删除过程会阻塞主线程,而是用 unlink 命令(Redis 4.0+)删除大 key,因为该命令的删除过程是异步的,不会阻塞主线程。

END