key

1、redis过期键的删除策略

Redis可以设置key的过期时间。Redis的过期策略就是指当Redis中缓存的key过期了,Redis如何处理。
过期策略通常有以下三种:

  • 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但会占用大量的CPU资源去处理过期的数据,影响缓存的响应时间和吞吐量。
  • 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
  • 定期清除:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
    (expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)

Redis中同时使用了惰性过期和定期过期两种过期策略。

2、通过expire来设置key 的过期时间,那么对过期的数据怎么处理呢?

除了缓存服务器自带的缓存失效策略之外(Redis默认的有6中策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种:

  1. 定时去清理过期的缓存;缺点是需要维护大量缓存的key。
  2. 当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。缺点是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂。

    3、Redis key的过期时间和永久有效分别怎么设置?

    通过expire或pexpire命令,客户端可以以秒或毫秒的精度为数据库中的某个键设置生存时间。
    与expire和pexpire命令类似,客户端可以通过expireat和pexpireat命令,以秒或毫秒精度给数据库中的某个键设置过期时间,可以理解为:让某个键在某个时间点过期。

    4、定期和惰性一定能保证删除数据吗?如果不能,Redis会有什么应对措施?

    并不能保证一定删除,Redsi有一个Redis 内存淘汰机制来确保数据一定会被删除。
    定期删除和惰性删除的工作流程:
    1、定期删除,Redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,Redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,Redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。
    2、于是,惰性删除派上用场。也就是说在你获取某个key的时候,Redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。
    3、采用定期删除+惰性删除也有问题,如果定期删除没删除key。然后你也没及时去请求key,也就是说惰性删除也没生效。这样, Redis 内存会越来越高。那么就应该采用内存淘汰机制。

    5、假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?使用keys指令会有什么影响?

    使用keys指令可以扫出指定模式的key列表:keys pre*。
    redis 的单线程的。keys 指令会导致线 程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时 候可以使用 scan 指令,scan 指令可以无阻塞的提取出指定模式的 key 列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间 会比直接用 keys 指令长。

    6、如果有大量的key需要设置同一时间过期,一般需要注意什么?

    如果大量的key过期时间设置的过于集中,到过期的那个时间点,Redis可能会出现短暂的卡顿现象(因为redis是单线程的)。严重的话可能会导致服务器雪崩,所以我们一般在过期时间上加一个随机值,让过期时间尽量分散。

    7、如何解决Redis的并发竞争Key问题

    Redis 的并发竞争 Key 的问题也就是多个系统同时对一个 key 进行操作,但是最后执行的顺序和期望的顺序不同,这样也就导致了结果的不同。
    推荐一种方案:分布式锁(zookeeper 和 Redis 都可以实现分布式锁)。(如果不存在 Redis 的并发竞争Key 问 题,不要使用分布式锁,这样会影响性能)
    基于zookeeper临时有序节点可以实现的分布式锁。大致思想为:每个客户端对某个方法加锁时,在zookeeper上的 与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。 判断是否获取锁的方式很简单,只需要判断有 序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁 无法释放,而产生的死锁问题。完成业务流程后,删除对应的子节点释放锁。
    在实践中,当然是从以可靠性为主。所以首推Zookeeper。

    分区

    1、介绍下分区技术,为什么要有分区,优势和不足在哪里

    Redis 分区技术(又称 Redis Partition)指的是将 Redis 中的数据进行拆分,然后把拆分后的数据分散到多个不同的 Redis 实例(即服务器)中,每个实例仅存储数据集的某一部分(一个子集),我们把这个过程称之为 Redis 分区操作。

    Redis 实例指的是一台安装了 Redis 服务器的计算机。

原因
分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。
分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。
优势

  • 提升服务器的性能
  • 提高了服务器的数据存储能力。

一方面,单台机器的 Redis 服务器,其网络 IO 能力和计算资源都是非常有限的,但是如果我们将请求分散到多台机器上,那么就能充分利用多台计算机的算力和网络带宽,从而整体上提升 Redis 服务器的性能。另一方面,随着存储数据的不断增加,单台机器的存储容量会达到极限,若将数据分散存储到多台 Redis 服务器上,其存储能力也将得到大幅度提升。
不足

  • 涉及操作多个 key 时,通常不被支持。这是由于批量操作的 key 会被映射到不同的 Redis 实例中,此时无法实现在一个实例中操作分散开的 key;
  • 不支持包含多个 key 的 Redis 事务;
  • 分区使用的粒度是key,不能使用一个非常长的排序key存储一个数据集
  • 当使用分区的时候,数据的处理变的非常复杂,比如需要处理多个 .rdb 或者 .aof 存储文件,并且还需要从多个 Redis 实例中备份数据;
  • 分区时动态扩容或缩容可能非常复杂。Redis集群在运行时增加或者删除Redis节点,能做到最大程度对用户透明地数据再平衡,但其他一些客户端分区或者代理分区方法则不支持这种特性。然而,有一种预分片的技术也可以较好的解决这个问题。

    2、分区常用方法

    “范围分区”和“哈希分区”。

  • 范围分区指的是将特定范围的 key 映射到指定的 Redis 实例上。

范围分区不仅简单,而且实用,适合许多的特定场景。但当存储的 key 不能按照范围划分时,那么范围分区就不再适用了,

  • 哈希分区与范围分区相比,它最显著的优势是适合任何形式的 key。

    3、分区实现方案有哪些?

  • 客户端分区就是在客户端就已经决定数据会被存储到哪个redis节点或者从哪个redis节点读取。大多数客户端已经实现了客户端分区。

  • 代理分区 意味着客户端将请求发送给代理,然后代理决定去哪个节点写数据或者读数据。代理根据分区规则决定请求哪些Redis实例,然后根据Redis的响应结果返回给客户端。redis和memcached的一种代理实现就是Twemproxy
  • 查询路由(Query routing) 的意思是客户端随机地请求任意一个redis实例,然后由Redis将请求转发给正确的Redis节点。Redis Cluster实现了一种混合形式的查询路由,但并不是直接将请求从一个redis节点转发到另一个redis节点,而是在客户端的帮助下直接redirected到正确的redis节点。