Redis相关面试题

1Redismemched有什么区别?为什么单线程的Redis比多线程的Memched效率要高?

区别:

数据支持类型:

Redis:

String(字符串):key-value 类型

Hash(哈希):字典(hashmap) Redis的哈希结构可以使你像在数据库中更新一个属性一样只修改某一项属性值

List(列表):实现消息队列

Set(集合):利用唯一性

Sorted Set(有序集合):可以进行排序 可以实现数据持久化

Bitmaps(位图)

HyperLogLog、Geo(地理信息定位)

Memched:简单的key/value数据类型

数据持久性:

Redis:Redis通过RDB(Redis DataBase)与AOF(Append Only File)持久化,可以将内存中的数据保存到硬盘中,然后重启之后在读取数据。

这里说明一下RDB和AOF的原理:

RDB:是在达到指定的时间或者操作次数后,自动将在内存中的数据写入磁盘(数据恢复时一致性和完整性较差,因为也许最后一次备份前就宕机了,适合数据量较大的数据恢复时候使用)

AOF:是日志形式,当数据写入内存中的时候,在日志文件下记录下所有写操作。(数据量较大时,数据的恢复缓慢)

注意:如果不需要持久化的功能,可以关闭。如果想要达到持久化的效果,建议两者都使用(RDB,AOF)

Memched:不支持数据的持久性的存储

内存利用情况:

使用简单的key-value存储的话,Memcached的内存利用率更高。

而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩(用哈希编码得到key值 查找再用产生哈希编码的算法,算回去,即可得到value,不用遍历),其内存利用率会高于Memcached。

Memcached默认使用Slab Allocation机制管理内存,主要思想是按照原先预定的大小分配内存大小,当客户端发过来数据的时候会选择一个最适合的地方给它储存,好处是效率高,

不会造成内存碎片,但是不好的一点就是分配的内存大小124字节,传进来的大小是100字节,那么24字节的内存也就浪费了。

事务:

Redis提供事务

menched不提供

线程:

Redis 单线程

menched多线程

性能区别:

Redis使用单核,

Memcached可以使用多核

在处理小的文件的时候Redis会比Memcached有更高的效率,但是在100KB以上的时候,Memcached的效率就会比Redis更高一点

2Redis有什么数据类型?都在哪些场景下使用?

String(字符串):key-value 类型

Hash(哈希):字典(hashmap) Redis的哈希结构可以使你像在数据库中更新一个属性一样只修改某一项属性值

List(列表):实现消息队列

Set(集合):利用唯一性,判断集合中是否有已存在的成员

Sorted Set(有序集合):可以进行排序

Bitmaps(位图)

HyperLogLog、Geo(地理信息定位)

3Redis的主从复制是怎么实现的?Redis的集群模式是如何实现的?Rediskey是如何寻址的?

主从复制:

a.从服务器连接主服务器,发送SYNC命令(写缓存命令);

b.主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;

  Bgsave 命令用于在后台异步保存当前数据库的数据到磁盘。

c.主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;

d.从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;

e.主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;

f.从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;

集群模式:Redis集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对key 使用

crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis

会根据节点数量大致均等的将哈希槽映射到不同的节点

Redis的key是如何寻址的?

redis采取链表的方式来存储多个哈希碰撞的键。也就是说,当根据key的哈希值找到该列表后,如果列表的长度大于1,那么我们需要遍历该链表来找到我们所查找的key。当然,一般情况下链表长度都为是1,所以时间复杂度可看作o(1)。我们知道如果哈希表数据量达到了一个很大的量级,那么冲突的链的元素数量就会很大,这时查询效率就会变慢,因为取值的时候redis会遍历链表。而随着数据量的缩减,也会产生一定的内存浪费。redis在设计时充分考虑了字典的增加和缩减,为了优化数据量增加时的查询效率和缩减时的内存利用率,redis进行了一系列操作,而处理的这个过程被称作rehash。

a、当拿到一个key后, redis 先判断当前库的0号哈希表是否为空,

即:if (dict->ht[0].size == 0)。如果为true直接返回NULL。

b、判断该0号哈希表是否需要rehash,因为如果在进行rehash,那么两个表中者有可能存储该key。如果正在进行rehash,将调用一次_dictRehashStep方法,_dictRehashStep 用于对数据库字典、以及哈希键的字典进行被动 rehash,这里不作赘述。

c、计算哈希表,根据当前字典与key进行哈希值的计算。

d、根据哈希值与当前字典计算哈希表的索引值。

e、根据索引值在哈希表中取出链表,遍历该链表找到key的位置。一般情况,该链表长度为1。

f、当 ht[0] 查找完了之后,再进行了次rehash判断,如果未在rehashing,则直接结束,否则对ht[1]重复345步骤。

4、使用Redis如何设计分布式锁?使用zk可以吗?如何实现?这两个哪个效率更高?

分布式锁:

a.在redis里创建一个key算加锁

输入命令:SET my:lock 随机值 NX PX 30000

NX:只有key不存在的时候才会设置成功,

PX 30000:30秒后锁自动释放

特点:别人创建的时候如果发现已经有了就不能加锁了。

释放锁:删除key

b. RedLock算法

例如有一个redis cluster,有5个redis master实例。

然后执行如下步骤获取一把锁:

1)获取当前时间戳,单位是毫秒

2)跟a类似,轮流尝试在每个master节点上创建锁,过期时间较短,一般就几十毫秒

3)尝试在大多数节点上建立一个锁,比如5个节点就要求是3个节点(n / 2 +1)

4)客户端计算建立好锁的时间,如果建立锁的时间小于超时时间,就算建立成功了

5)要是锁建立失败了,那么就依次删除这个锁

6)只要别人建立了一把分布式锁,你就得不断轮询去尝试获取锁

zk分布式锁

某个节点尝试创建临时znode,此时创建成功了就获取了这个锁;这个时候别的客户端来创建锁会失败,只能注册个监听器监听这个锁。释放锁就是删除这个znode,一旦释放掉就会通知客户端,然后有一个等待着的客户端就可以再次重新枷锁。

效率比较:

redis分布式锁,其实需要自己不断去尝试获取锁,比较消耗性能

 zk(zookeeper)分布式锁,获取不到锁注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小

zk分布式锁会自动尝试获取锁自然是比自己去获取锁效率更高

5、知道Redis的持久化吗?都有什么缺点和优点?具体底层实现呢?

持久化有两种方案:RDB和AOF

RDB:

优点:最大化发挥redis的性能,主进程不需要进行任何I/O操作,只需要派生一个子进程来处理,文件非常紧凑,恢复数据的效率高。

缺点:数据恢复时一致性和完整性较差,因为也许最后一次备份前就宕机了,那么在最后一次备份到宕机中间的数据是不会存在的

AOF:

优点:能保持数据的一致性和完整性

缺点:AOF文件比RDB文件大,在读取过程中,会比RDB更慢一些。

底层实现

RDB:是在达到指定的时间或者操作次数后,自动将在内存中的数据写入磁盘

AOF:是日志形式,当数据写入内存中的时候,在日志文件下记录下所有写操作。

6Redis过期策略都有哪些?

定期删除:指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。

惰性删除:在你获取某个key的时候,redis会检查一下 ,这个key如果设置了过期时间那么是否过期了,如果过期了此时就会删除,不会给你返回任何东西。

内存淘汰:

1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错 

2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key 

3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key

4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key

5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key

6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除

 

 

原文地址:https://www.cnblogs.com/7-30-onlyone/p/11330206.html