Redis面试题总结

不羁岁月 提交于 2020-01-19 15:12:42
  • 如何用Redis做异步队列

    • 一般使用list结构作为队列,rpush生产消息,lpop消费消息,当lpop没有消息的时候,需要适当sleep一会再重试
    • 或者不用sleep使用blpop在没有消息的时候,它会阻塞住直到消息的到来
    • 可以使用pub/sub主题订阅者模式,可以实现1:N的消息队列
    • pub/sub缺点:在消费者下线的情况下,生产的消息会丢失,要使用专业的消息队列(RocketMQ)
  • Redis如何实现延时队列

    • 使用sortedset,拿时间戳作为score,消息内容作为key调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理
  • 机器突然掉电会怎么样

    • 取决于AOF日志sync属性的配置,如果不要求性能,在每条指令时都sync一下磁盘,就不会丢失数据。但在高性能的要求下一般都是使用定时sync。
  • Pipeline有什么好处,为什么要使用Pipeline

    • 可以将多次IO往返的时间缩减为一次,前提是pipeline执行的指令之间没有因果相关性。使用redis-benchmark进行压测的时候可以发现影响redis的QPS峰值的一个重要因素是pipeline批次指令的数目。
  • 多个操作系统同时操作Redis带来的数据问题

    • 可以基于Zookeeper实现分布式锁,每个系统通过Zookeeper获取分布式锁,确保同一时间,只有一个系统实例在操作某个key别人都不允许读和写。
    • 每次要写之前都要先判断一下当前这个Value的时间戳是否比缓存里的Value的时间戳要新。
  • 数据一致性问题

    • 使用串行化:即读请求和写请求串行化,串行到一个内存队列中。
    • 但是会导致系统的吞吐量大幅度降低
    • 顺序不会乱但是并发高了,这队列很容易阻塞,反而成为了系统的瓶颈
  • 最经典的KV、DB读写模式

    • 最经典的缓存+数据库读写模式就是Cache Aside Pattern
      • 读的时候先读缓存,缓存没有的话,就读数据库,然后取出数据后放入到缓存中,同时返回响应
      • 更新的时候,先更新数据库,然后在删除缓存。
  • 为什么是删除缓存不是更新缓存

    • 在复杂点的缓存场景,缓存不单单是数据库直接取出的值
    • 更新缓存的代价较高,用到缓存的地方再去计算缓存
  • Redis和Memcached有啥区别

    • Memcached(MC)
      • 特点:
      • 处理请求时使用多线程异步IO的方式,可以合理利用CPU多线程的游戏,性能优秀
        • 功能简单,使用内存存储数据
        • 对缓存的数据可以设置失效期,过期数据会自动被清除
        • 失效的策略采用延迟失败,就是当再次使用数据时检查是否失效
        • 当容量存满时,会对缓存中的数据进行剔除,剔除时除了会对过期key进行清理还会按照LRU策略对数据进行剔除
      • 限制:
        • key不能超过250个字节
        • value不能超过1M个字节
        • key的最大失效时间是30天
        • 只支持K-V结构,不提供持久化和主从同步的功能
    • Redis:
      • 特点
        • 采用单线程模式处理请求:
          • 采用了非阻塞的异步事件处理机制
          • 缓存数据都是内存操作,IO时间不会太长,单线程可以避免线程上下文切换产生的代价
        • Redis支持持久化,不仅仅可以作为缓存,也可以作为NoSQL数据库
        • 支持多种数据结构
        • Redis提供主从同步机制,以及Cluster集群部署能力,能够提供高可用服务
  • Redis的线程模型

    • Redis内部使用文件事件处理器file event handler,这个文件处理器是单线程的,所以Redis才叫做单线程的模型。它采用IO多路复用机制同时监听多个Socket,根据Socket上的事件来选择对应的处理器进行处理
    • 文件事件处理器的结构包括四个部分
      • 多个Socket
      • IO多路复用程序
      • 文件事件分配器
      • 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
    • 多个Socket可能会并发产生不同的操作,每个操作对于不同的文件事件,但是IO多路复用程序会监听多个Socket,会将 Socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。
  • 缓存有哪些类型

    缓存是高并发场景下提高热点数据访问性能的一个有效手段。

    • 本地缓存:就是在进程的内存中进行缓存,比如我们的JVM堆中,可以用LRUMap来实现,也可以使用Ehcache这样的工具来实现;本地缓存是内存访问,没有远程交互开销,性能最好,但是受制于单机容量,一般缓存较小且无法扩展
    • 分布式缓存:一般去油良好的水平扩展能力,对较大数据量的场景也能应对自如。缺点是需要进行远程请求,性能远不如本地缓存
    • 多级缓存:实际业务中一般使用多级缓存,本地缓存只保存访问频率最高的部分热点数据,其他的热点数据放在分布式缓存中。
  • 淘汰策略:

    • FIFO淘汰最早数据、LRU 剔除最近最少使用、和 LFU 剔除最近使用频率最低的数据几种策略。
      • noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入命令,但是DEL和几个例外)
      • allkeys-lru:尝试回收最少使用的键(LRU),
      • volatile-lru:尝试回收最少使用的键(LRU)。但仅限于在过期集合的键,
      • allkeys-random:回收随机的键
      • volatile-random:回收随机的键,但仅限于在过期集合的键
      • volatile-ttl:回收在过期集合的键。并且优先回收存活时间(TTL)较短的键。
  • Redis的高级用法:

    • Bitmap:位图是支持按bit位来存储信息,可以用来实现布隆过滤器(BloomFilter)
    • HyperLogLog:提供不精确的去重计数功能,比较适合用来做大规模数据的去重统计,例如统计UV
    • Geospatial:可以用来保存地理位置,并作为位置距离计算或者根据半径计算位置
    • pub/sub:功能是订阅发布功能,可以用作简单的消息队列
    • Pipeline:可以批量执行一组指令,一次性返回全部结果,可以减少频繁的请求应答。
    • Lua:Redis支持提交Lua脚本来执行一系列的功能
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!