阅读 434

redis缓存 面试一则

redis 和 memcached 有什么区别?redis的线程模型是什么?为什么单线程比多线程memcached效率要高得多(为什么redis单线程还可以支撑高并发)?

回答:
redis和memcached区别

    1、redis支持服务器端的数据操作:redis比memcached数据结构多和支持更丰富的数据操作
    2、redis可以支持复杂的结构和操作
    3、redis官方致辞集群模式
复制代码

redis的线程模型(用redis还是要了解一点线程模型)

    1、文件事件处理器
      redis基于reactor(java的Nio就是一个reactor模型)模式开发了网络事件处理器,这个处理器叫做文件事件处理器,
      file event handler。这个文件事件处理器,是单线程的,redis所以才叫做单线程的模型,
      采用IO多路复用机制同时监听多个socket,根据socket上的时间来选择对应的事件处理器来处理这个事件
      
      如果被监听的socket准备好执行accept、read、write、close
      等操作的时候,相应的文件事件就会产生,这个时候文件处理器就会调用之前关联的时间处理器来处理事件
      
      文件处理器的结构包含4个部分:多个socket,IO多路复用程
      序,文件事件分派器、事件处理器(命令请求处理器、命令回复处理器、连接应答处理器,等等)。
      
      相应的多个socket会产生多个不同的操作,每个操作对应不同的文件事件,但是IO多路复用程序虽然会监听多个socket,但
      是会把socket放到一个队列中,这样依次选择对应的事件处理器来处理
    
    2、文件事件
    
    当socket变得可读时(比如客户端对redis执行write操作,或者close操作),或者有新的可以应答的socket出现,socket就会产生一个AE_READABLE事件。
    
    当socket便可可以读写的时候(客户端对redis执行read操作),socket会产生一个AE_WRITABLE事件
    
    IO多路复用程序可以监听AE_REABLE 和 AE_WRITABLE两种事假,要是一个socket同时产生了两种事件,那么文件分派器优先处理前者(读)其次才是写
    
    3、文件事件处理器
    
    如果是客户端要连接redis,那么会为socket关联连接应答处理器
    
    如果客户端要写数据到redis,为socket关联命令请求处理器
    
    如果要读数据,为socket关联命令回复处理器
    
    4、客户端与redis通信的一次流程
    
    在redis启动初始化的时候,redis会将连接应答处理器何AE_READABLE事件关联起来,
    接着如果一个客户端跟redis发起连接此时会产生一个AE_READABLE事件,然后由连接应答处理器跟客户端建立连接,创建客户端对应的socket,同时将这个socket的AE_READABLE事件跟命令请求处理器关联起来
    
    当客户端向redis发起请求的时候(不管读还是写),首先就会在socket产生一个AE_READABLE事件,然后由对应的命令请求处
    理器来处理。这个命令请求处理器就会从socket中读取相关数据,然后进行执行和处理
    
    接着redis这边准备好了给客户端的相应数据后,就会将socket的AE_WRITABLE事件跟命令回复处理器关联起来
    当客户端这边准备好读取相应数据时,就会在socket上产生一个AE_WRITABLE事件,
    会由对应的命令回复处理器来处理,就是讲准备好的相应数据写入socket,供客户端来读取
    
    命令回复处理器写完之后,就会删除这个socket的AE_WRITABLE事件和命令回复处理器的关联关系
复制代码

为什么redis单线程模型效率这么高

    1、纯内存操作
    2、核心是基于非阻塞的IO多路复用机制
    3、不用频繁切换上下文
复制代码

redis都有哪些数据类型?分别在哪些场景下使用合适?

(如果问这个问题应该觉得你对技术没有深入研究过,看看你会不会用)

    1、string 最基本的类型,普通set和get,做简单的kv缓存
    2、hash: 类似map的一种结构,前提是简单对象(没有嵌套其他对象)给缓存在redis里,然后每次读写缓存的时候,就可以操作hash里的某个字段
    
    比如 key=abc value={"id":12,"age":12}, 可以直接操作age 修改为 20.
    
    3、list 有序列表,这个可以来个骚操作
    比如,做分页,类似那种下拉分页的东西
    简单的消息队列,粉丝列表
    
    4、set 无序集合,自动去重
    基于set玩交集、并集和差集,比如交集,两个人粉丝列表整一个交集,看看共同好友
    
    5、sortedset
    可以排序的去重,做排行榜
    将每个用户以及其对应的什么分数写入进去,zadd board score username,接着zrevrange board 0 99,就可以获取排名前100的用户;zrank board username,可以看到用户在排行榜里的排名
    
    zadd board 85 zhangsan
    zadd board 72 wangwu
    zadd board 96 lisi
    zadd board 62 zhaoliu
    
    96 lisi
    85 zhangsan
    72 wangwu
    62 zhaoliu

    zrevrange board 0 3
    
    获取排名前3的用户
    
    96 lisi
    85 zhangsan
    72 wangwu
复制代码

redis过期策略有哪些?内存淘汰机制有哪些?手写一个LRU代码实现?

1、设置过期时间,set key的时候都可以给一个过期时间,假如过期后redis怎么对这个key删除的? 答:定期删除+惰性删除

定期删除就是每个100ms随机抽取一些设置了过期时间的key,如果过期了就删除,但是会有一个问题,因为随机查找所以有些会漏。

但是你再获取这key的时候,却找不到这个时候就是惰性删除,在你获取key的时候,redis会检查一下,这个key如果过期了,就删除不给你返回什么东西。

但是这样还有一个问题就是,假如删除没有删除,然后你系统也没有查key,就这样一直留在内存里,redis内存就崩了。 这个时候就会走内存淘汰机制

2、内存淘汰 如果redis的内存占用过多的时候,这个时候就会进行内存淘汰

    redis 10个key,现在已经满了,redis需要删除掉5个key
    
    1个key,最近1分钟被查询了100次
    1个key,最近10分钟被查询了50次
    1个key,最近1个小时倍查询了1次
    
    1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没人用吧,实在是太恶心了
    2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
    3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key,这个一般没人用吧,为啥要随机,肯定是把最近最少使用的key给干掉啊
    4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key(这个一般不太合适)
    5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
    6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除复制代码
关注下面的标签,发现更多相似文章
评论