首页 > 数据库 >Redis 面试题

Redis 面试题

时间:2023-06-08 16:15:23浏览次数:29  
标签:面试题 缓存 lock Redis 加锁 key 客户端

1. Redis 是什么?

Redis 是一种基于内存的数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景

2. Redis 有哪些数据类型?

  • 5 种基础数据结构:String(字符串)、List(列表)、Set(集合)、Hash(哈希)、Zset(有序集合)。
  • 3 种特殊数据结构:HyperLogLogs(基数统计)、Bitmap (位存储)、Geospatial (地理位置)。

String 是最常用的数据类型,String 类型的应用场景:缓存对象、常规计数、分布式锁、共享 session 信息等。

2.1 缓存对象

使用 String 来缓存对象有两种方式:

  • 直接缓存整个对象的 JSON,命令例子: SET user:1 '{"name":"xiaolin", "age":18}'
  • 采用将 key 进行分离为 user:ID:属性,采用 MSET 存储,用 MGET 获取各属性值,命令例子: MSET user:1:name xiaolin user:1:age 18 user:2:name xiaomei user:2:age 20

2.2 使用 Redis实现分布式锁

SET 命令有个 NX 参数可以实现「key不存在才插入」,可以用它来实现分布式锁:

  • 如果 key 不存在,则显示插入成功,可以用来表示加锁成功;
  • 如果 key 存在,则会显示插入失败,可以用来表示加锁失败。

一般而言,还会对分布式锁加上过期时间,分布式锁的命令如下:

SET lock_key unique_value NX PX 10000
  • lock_key 就是 key 键;
  • unique_value 是客户端生成的唯一的标识;
  • NX 代表只在 lock_key 不存在时,才对 lock_key 进行设置操作;
  • PX 10000 表示设置 lock_key 的过期时间为 10s,这是为了避免客户端发生异常而无法释放锁。(EX 的单位为秒)

而解锁的过程就是将 lock_key 键删除,但不能乱删,要保证执行操作的客户端就是加锁的客户端。所以,解锁的时候,我们要先判断锁的 unique_value 是否为加锁客户端,是的话,才将 lock_key 键删除。这里提一点:如何保证解锁的客户端为加锁客户端呢?可以给 key 再加一个随机不重复的 id,这样 key 唯一了,只有加锁的客户端才能解锁。

可以看到,解锁是有两个操作,这时就需要 Lua 脚本来保证解锁的原子性,因为 Redis 在执行 Lua 脚本时,可以以原子性的方式执行,保证了锁释放操作的原子性。

// 释放锁时,先比较 unique_value 是否相等,避免锁的误释放
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

这样一来,就通过使用 SET 命令和 Lua 脚本在 Redis 单节点上完成了分布式锁的加锁和解锁。

3. 为什么用 Redis 作为 MySQL 的缓存?

主要是因为 Redis 具备「高性能」和「高并发」两种特性

  1. 高性能:假如用户第一次访问 MySQL 中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据缓存在 Redis 中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了,操作 Redis 缓存就是直接操作内存,所以速度相当快。
  2. 高并发:单台设备的 Redis 的 QPS(Query Per Second,每秒钟处理完请求的次数) 是 MySQL 的 10 倍。Redis 单机的 QPS 能轻松破 10w,而 MySQL 单机的 QPS 很难破 1w。

4. Redis为何这么快?

Redis 内部做了非常多的性能优化,比较重要的有下面 3 点:

  1. Redis 基于内存,内存的访问速度是磁盘的上千倍;
  2. Redis 基于 Reactor 模式设计开发了一套高效的事件处理模型,主要是单线程事件循环和 IO 多路复用;
  3. Redis 内置了多种优化过后的数据结构实现,性能非常高。

5. 开发中常用的 Redis 命令有哪些?

  • set:设置值,比如:set key value
  • get:获取值,比如:get key
  • exists:检查给定 key 是否存在,比如:EXISTS KEY_NAME
  • del:删除 key,比如:DEL KEY_NAME
  • expire:为给定 key 设置过期时间,以秒为单位,比如: Expire KEY_NAME TIME_IN_SECONDS
  • ttl:以秒为单位,返回给定 key 的剩余生存时间
  • mset:同时 set 多个值,比如:MSET key1 value1 key2 value2 .. keyN valueN
  • mget:获取所有(一个或多个)给定 key 的值,比如:MGET KEY1 KEY2 .. KEYN
  • hset:hash 命令,存储的值哈希表,一个 key 对应一个哈希表。比如:hset key field1 value1 field2 value2
  • hget:获取哈希表。比如:hget key
  • hexists:判断哈希表 key 是否存在
  • hedel:删除哈希表 key

6. Redis 如何实现数据不丢失?

Redis 共有三种数据持久化的方式:

  • AOF 日志:Redis 在执行完一条写操作命令后,就会把该命令以追加的方式写入到一个文件里,然后 Redis 重启时,会读取该文件记录的命令,然后逐一执行命令的方式来进行数据恢复。
  • RDB 快照:将某一时刻的内存数据,以二进制的方式写入磁盘;
  • 混合持久化方式:Redis 4.0 新增的方式,集成了 AOF 和 RBD 的优点;

标签:面试题,缓存,lock,Redis,加锁,key,客户端
From: https://www.cnblogs.com/cloudrich/p/17466765.html

相关文章

  • redis 安装fatal error: jemalloc/jemalloc.h: No such file or directory 错误
    转自;https://www.cnblogs.com/oxspirt/p/11392437.html 问题现象: 我第一次安装redis时,没有安装gcc,报错了,然后安装好gcc,后再次执行make命令,安装redis就出现了如上的错误 网上错误解决办法网上大部分解决办法都是错误的,如下文:(错误解决办法)makeMALLOC=libc正确解决......
  • Redis系列15:使用Stream实现消息队列(精讲)
    Redis系列1:深刻理解高性能Redis的本质Redis系列2:数据持久化提高可用性Redis系列3:高可用之主从架构Redis系列4:高可用之Sentinel(哨兵模式)Redis系列5:深入分析Cluster集群模式追求性能极致:Redis6.0的多线程模型追求性能极致:客户端缓存带来的革命Redis系列8:Bitmap实现亿万级......
  • 杭州字节、懂车帝面试题___整理汇总
     =================================字节懂车帝一面  :2023年6月8日  gxr  1.自我介绍2.你们为什么要做对商家判责3.你们这个积分的加减对商家有什么影响吗?4.刚刚提到了百分之95是什么?==平台对建议预售量和商家的预售量对比5.预售量和备货量之间的关系是什么?6.对于商家判......
  • 十、Redis主从复制
    读操作:主库、从库都可以接收;写操作:首先到主库执行,然后,主库将写操作同步给从库。主从第一次同步第一阶段,主从库间建立连接、协商同步的过程,主要是为全量复制做准备。从库和主库建立起连接,主库确认回复后,就可以开始同步了。具体来说,从库给主库发送psync命令,psync命令包含了......
  • 十一、Redis扩容如何保证哈希一致性
    横向扩容,保证哈希一致性一致性哈希将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形)下一步将各个服务器使用Hash进行一个哈希,具体可以选择服务器的ip或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置......
  • 十三、Redis并发竞争问题
    多客户端同时并发写一个key,可能本来应该先到的数据后到了,导致数据版本错了。或者是多客户端同时获取一个key,修改值之后再写回去,只要顺序错了,数据就错了首先使用分布式锁,确保同一时间,只能有一个系统实例在操作某个key然后修改key的值时,要先判断这值的时间戳是否比缓存里的值的时......
  • 五、Redis内存消耗
    从性能上来说,内存占用过高会引起Reids响应变慢从高可用上来说,内存过大可能会会引起部分数据丢失,故障恢复变慢Redis内存消耗主要在于其主进程消耗和子进程消耗。而主进程消耗又主要包括自身内存、对象内存、缓冲区内存、内存碎片五个方面1、自身内存指Redis进程自身所占用的内......
  • redis应用场景--记录文章,图文,或者视频的浏览次数
    在阅读博客文章时,你可以看到一篇文章被阅读的次数,如果使用mysql,那么在设计article表时,就必须设置一个view_count字段来记录这篇文章被阅读的次数。但这种方式相比于使用redis,并不是一种好的办法,原因在于,每次更新view_count字段的值都是一个比较费力的过程。首先,程序需要根据文......
  • redis应用场景--实现布隆过滤器
    简述布隆过滤器的实现思路:假设有一个长度为n的比特数组,bit_array,数组里的每一位都是0,对于一个url或者是其他数据,使用hash算法计算出url的散列值,这个散列值当然是一个整数,暂且命名为index,index=index%n,确保index的值小于n,查看bit_array[index]是否等于1,如果等于1,表示该url已......
  • org.springframework.data.redis.RedisSystemException: Redis exception; nested exc
    springBoot+redis.程序隔一段时间会莫名其妙的报Redis的错误.报错如下:org.springframework.data.redis.RedisSystemException:Redisexception;nestedexceptionisio.lettuce.core.RedisException:java.io.IOException:Connectionresetbypeer百度得知说:是因为re......