面试题之Redis篇

Redis支持哪些数据类型

  • string
  • list
  • set
  • hash
  • zset(sorted set)

list和set数据类型的区别

  • list有序,set无序
  • list可以有重复元素,set不能有重复元素

用Redis实现分布式锁的关键点

  • 加锁用setnx key thread_id expire 10s,其中:只有key不存在时才加锁,实现锁的基本定义,value中放占用锁的线程ID,用于解锁时校验,同时设置超时时间,防止代码出问题导致锁一直不释放,一般超时时间要远大于正常程序执行时间;
  • 解锁用lua脚本,保证解锁操作的原子性,先判断key的value是不是当前线程ID,如果不是,则返回,如果是,才解锁;

zset的底层数据结构

  • 当元素少,且zset总大小比较小的时候,底层用的是ziplist,压缩列表,压缩列表占用内存少,但插入和查询元素时只能遍历,复杂度为O(n),在元素少时比较好;
  • 当元素超过一个阈值或大小超过一个阈值时,底层会转成skiplist,跳表,跳表占用内存比压缩列表多,但插入和查询元素时复杂度为O(logn),性能更好,且相比于红黑树,跳表实现更简单,这也是redis选择跳表的原因之一。

Redis过期键的清理策略

  • Redis有两种清理策略:惰性清理和定期清理;
  • 惰性清理是指在查询元素时先检查元素是否过期,如果过期了,就删除元素并返回不存在;
  • 定期清理是指后台定期启动子线程去执行清理过期键的逻辑,并且清理时会采用随机抽取元素,检查是否过期,如果过期,则清理,同时,检查这次抽取的元素过期比例,如果比例大于某个阈值,则继续清理过程,如果小于阈值,则停止清理。

为什么要使用两种清理策略

  • 惰性清理对cpu友好,对内存不友好,如果只使用惰性清理,可能会浪费内存;
  • 定期清理对内存友好,对cpu不友好;如果只使用定期清理,可能会导致清理时redis反应慢,甚至卡死;
  • 两种策略结合,可以在保证清理逻辑不影响业务使用的同时,避免过期键占用过多内存。

发表评论