##java面试题大全
详细面试题-持续更新中-点击跳转
点赞、收藏、加关注
·
·
java基础面试题
- ##java面试题大全
- 1、什么是 Redis
- 2、Redis 的数据结构类型
- 3、Redis 为什么快
- 4、什么是跳跃表
- 5、什么是 I/O 多路复用
- 6、什么是缓存击穿、缓存穿透、缓存雪崩
- 7、什么是布隆过滤器
- 8、热点 Key 问题
- 1)热点 Key 怎么样会影响到 Redis 服务
- 2)如何识别到热点 Key
- 3)如何解决 热点 Key 问题
- 9、Redis 过期策略和内存淘汰策略
- 10、Redis 持久化
- 11、实现 Redis 的高可用
- 1)主从集群
- 2)哨兵模式
- 3)分片集群
- 12、使用过 Redis 分布式锁嘛
- 13、Redisson 原理
- 14、什么是 Redlock 算法
- 15、MySQL 与 Redis 如何保证双写一致性
- 16、Redis 事务机制
- 17、Redis 的 Hash 冲突怎么办
- 18、Redis 底层,使用的什么协议
1、什么是 Redis
Redis,英文全称是 Remote Dictionary Server(远程字典服务),是一个开源的使用 C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。与 MySQL 数据库不同的是,Redis 的数据是存在内存中的。它的读写速度非常快,每秒可以处理超过 10 万次读写操作。因此 Redis 被广泛应用于缓存,另外,Redis 也经常用来做分布式锁。除此之外,Redis 支持事务、持久化、LUA 脚本、多种集群方案
2、Redis 的数据结构类型
** 1.String **
- 简介:字符串。String 是 Redis 最基础的数据结构类型,它是二进制安全的,可以存储图片或者序列化的对象,值最大存储为 512M
- 应用场景:共享 Session、分布式锁、计数器
- 拓展:C 语言的字符串是 char[] 实现的,而 Redis 使用 SDS(simple dynamic string)封装。SDS 会保存空闲的长度、已使用的长度、实际保持的内容值。
- 字符串长度处理:Redis 获取字符串长度,时间复杂度为 O(1),而 C 语言中,需要从头开始遍历,复杂度为 O(n)
- 空间预分配:字符串修改越频繁的话,内存分配越频繁,就会消耗性能,而 SDS 修改和空间扩充,会额外分配未使用的空间,减少性能损耗
- 惰性空间释放:SDS 缩短时,不是回收多余的内存空间,而是 free 记录下多余的空间,后续有变更,直接使用 free 中记录的空间,减少分配
- 二进制安全:Redis 可以存储一些二进制数据,在C语言中字符串遇到 ‘\0’ 会结束,而 SDS 中标志字符串结束的是 len 属性
** 2.Hash **
- 简介:哈希。哈希类型是指 v(值)本身又是一个键值对(k-v)结构
- 应用场景:缓存用户对象信息
** 3.List **
- 简介:列表。列表类型是用来存储多个有序的字符串
- 应用场景:消息队列、文章列表
- 拓展:lpush+lpop=Stack(栈);lpush+rpop=Queue(队列);lpsh+ltrim=Capped Collection(有限集合);lpush+brpop=Message Queue(消息队列)
** 4.Set **
- 简介:集合。集合类型也是用来保存多个的字符串元素,但是不允许重复元素
- 应用场景:用户标签、生成随机数抽奖、用户点赞
- 拓展:smembers 和 lrange、hgetall 都属于比较重的命令,如果元素过多存在阻塞 Redis 的可能性,可以使用 sscan 来完成
** 5.ZSet **
- 简介:有序集合。已排序的字符串集合,同时元素不能重复
- 应用场景:排行榜
** 6.Geo **
- 简介:地图位置。Redis3.2 推出的,地理位置定位,用于存储地理位置信息,并对存储的信息进行操作
- 应用场景:用户定位,附近商家
** 7.Bitmaps **
- 简介:位图。用一个比特位来映射某个元素的状态,在 Redis 中,它的底层是基于字符串类型实现的,可以把 Bitmaps 成作一个以比特位为单位的数组
- 应用场景:签到、用户是否在线状态
** 8.HyperLogLog **
- 简介:用来做基数统计算法的数据结构
- 应用场景:统计网站的UV
3、Redis 为什么快
- 基于内存存储实现:Redis 基于内存存储实现的数据库,相对于数据存在磁盘的 MySQL 数据库,省去磁盘 I/O 的消耗
- 高效的数据结构:Redis 自己也封装了一些数据结构,可以有效的提高效率。如:String 的动态字符串结构、ZSet 的跳跃表
- 合理的数据编码:Redis 每种基本类型,对应多种数据结构,使用什么样编码,是 Redis 设计者总结优化的结果,Redis 会自动的根据元素个数、元素内容大小选择合适的数据编码。如:
- String:如果存储数字的话,是用 int 类型的编码;如果存储非数字,小于等于 39 字节的字符串,是 embstr 编码;大于 39 个字节,则是 raw 编码。
- List:如果列表的元素个数小于 512 个,列表每个元素的值都小于 64 字节(默认),使用 ziplist 编码,否则使用 linkedlist 编码
- Zset:当有序集合的元素个数小于 128 个,每个元素的值小于 64 字节时,使用 ziplist 编码,否则使用 skiplist(跳跃表)编码
- 合理的线程模型:采用 I/O 多路复用。I/O 多路复用技术可以让单个线程高效的处理多个连接请求,而 Redis 使用用 epoll 作为 I/O 多路复用技术的实现。并且,Redis 自身的事件处理模型将 epoll 中的连接、读写、关闭都转换为事件,不在网络 I/O 上浪费过多的时间
- 虚拟内存机制:Redis 直接自己构建了 VM 机制 ,不会像一般的系统会调用系统函数处理,会浪费一定的时间去移动和请求。虚拟内存机制就是暂时把不经常访问的数据(冷数据)从内存交换到磁盘中,从而腾出宝贵的内存空间用于其它需要访问的数据(热数据)。通过 VM 功能可以实现冷热数据分离,使热数据仍在内存中、冷数据保存到磁盘。这样就可以避免因为内存不足而造成访问速度下降的问题
4、什么是跳跃表
- 跳跃表是有序集合 zset 的底层实现之一
- 跳跃表支持平均 O(logN) 复杂度的节点查找,还可以通过顺序性操作批量处理节点
- 跳跃表就是在链表的基础上,增加多级索引提升查找效率
5、什么是 I/O 多路复用
- redis的网络模型是 io 多路复用+事件派发,有多个事件处理器,如连接应答处理器、[命令回复处理器]、命令请求处理器([接受请求参数、把数据转换成redis命令]、执行命令写入到缓冲队列、[由命令回复处理器进行响应给客户端结果])。[多线程的处理]
- Redis 是基于内存的,所以它的性能瓶颈是网络 IO,IO 多路复用技术就是为了实现高效的网络请求,6 版本之后引入多线程也是为了解决这个问题
- 阻塞 io:需要内核缓冲区等待数据,然后从内核缓冲区拷贝到用户缓冲区
- 非阻塞 io:请求内核缓冲区的数据,没有就返回异常信息,然后再去请求,直到有数据,然后从内核缓冲区拷贝到用户缓冲区
- io 多路复用:使用单个线程如使用 select 函数可以监听多个 socket(客户端的连接),并在某个 socket 可读可写时得到通知,避免无效的等待。使用 select 或者 poll 实现不会知道是哪个 socket 就绪的,使用 epoll 用户进程会知道就绪的 socket
6、什么是缓存击穿、缓存穿透、缓存雪崩
** 缓存击穿: **
- 产生原因:指热点 Key 在某个时间点过期的时候,而恰好这个时间点有大量的并发请求这个热点 Key,从而大量的请求请求到数据库,导致数据库压力过大甚至宕机
- 解决方法:
- 使用互斥锁:缓存失效时,不是立即去加载数据库数据,而是先使用某些带成功返回的原子操作命令,如 Redis 的 setnx 去操作,成功的时候,再去加载数据库数据和设置缓存。否则就去重试获取缓存,这样就可以保证只有一个请求请求数据库
- 设置永不过期:是指不设置过期时间
** 缓存穿透: **
- 产生原因:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而导致数据库压力过大甚至宕机
- 解决方法:
- 校验非法请求:在 API 入口,对参数进行校验,过滤非法值
- 缓存空值:如果查询数据库为空,可以给缓存设置个空值,或者默认值
- 使用布隆过滤器:使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查,可能存在误判,key 如果不存在那一定不存在,如果判断 key 存在,也有可能是不存在的
** 缓存雪崩: **
- 产生原因:指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,导致数据库压力过大甚至宕机
- 解决方法:
- 过期时间分散:缓存雪奔一般是由于大量数据同时过期造成的,对于这个原因,可通过均匀设置过期时间解决,比如添加随机数
- 构建高可用集群:Redis 故障宕机也可能引起缓存雪奔,这就需要构造Redis高可用集群了
7、什么是布隆过滤器
- 布隆过滤器是一种占用空间很小的数据结构,它由一个很长的二进制向量和一组Hash映射函数组成,它用于检索一个元素是否在一个集合中,空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难
- 布隆过滤器原理:假设我们有个集合 A,A 中有 n 个元素。利用 k 个哈希散列函数,将 A 中的每个元素映射到一个长度为 a 位的数组 B 中的不同位置上,这些位置上的二进制数均设置为 1。如果待检查的元素,经过这 k 个哈希散列函数的映射后,发现其 k 个位置上的二进制数全部为 1,这个元素很可能属于集合 A,反之,一定不属于集合 A
- 如何降低误判率:搞多几个哈希函数映射,降低哈希碰撞的概率;增加 B 数组的 bit 长度
8、热点 Key 问题
在 Redis 中,把访问频率高的 Key,称为热点 Key。如果某一热点 Key 的请求到服务器主机时,由于请求量特别大,可能会导致主机资源不足,甚至宕机,从而影响正常的服务
1)热点 Key 怎么样会影响到 Redis 服务
- 用户消费的数据远大于生产的数据,如秒杀、热点新闻等读多写少的场景
- 请求分片集中,超过单 Redis 服务器的性能,比如固定名称 Key,Hash 值落入同一台服务器,瞬间访问量极大,超过机器瓶颈,产生热点 Key 问题
2)如何识别到热点 Key
- 凭经验判断哪些是热Key;
- 客户端统计上报;
- 服务代理层上报
3)如何解决 热点 Key 问题
- Redis 集群扩容,增加分片副本,均衡读流量
- 将热点 Key 分散到不同的服务器中
- 使用二级缓存,即 JVM 本地缓存,减少 Redis 的读请求
9、Redis 过期策略和内存淘汰策略
** 过期策略:**
- 定时过期:每个设置过期时间的 Key 都需要创建一个定时器,到过期时间就会立即对 Key 进行清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的 CPU 资源去处理过期的数据,从而影响缓存的响应时间和吞吐量
- 惰性过期:只有当访问一个 Key 时,才会判断该 Key 是否已过期,过期则清除。该策略可以最大化地节省 CPU 资源,却对内存非常不友好。极端情况可能出现大量的过期 Key 没有再次被访问,从而不会被清除,占用大量内存
- 定期过期:每隔一定的时间,会扫描一定数量的数据库的字典中一定数量的 Key,并清除其中已过期的 Key。该策略是前两者的一个折中方案。一般同时使用了惰性过期和定期过期两种策略
** 淘汰策略:**
- volatile-lru:当内存不足以容纳新写入数据时,从设置了过期时间的 Key 中使用 LRU(最近最少使用) 算法进行淘汰
- allkeys-lru:当内存不足以容纳新写入数据时,从所有 Key 中使用 LRU 算法进行淘汰
- volatile-lfu:4.0 版本新增,当内存不足以容纳新写入数据时,在过期的 Key 中,使用 LFU(使用频率最少) 算法进行删除 Key
- allkeys-lfu:4.0 版本新增,当内存不足以容纳新写入数据时,从所有 Key 中使用 LFU 算法进行淘汰
- volatile-random:当内存不足以容纳新写入数据时,从设置了过期时间的 Key 中,随机淘汰数据
- allkeys-random:当内存不足以容纳新写入数据时,从所有 Key 中随机淘汰数据
- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的 Key 中,根据过期时间进行淘汰,越早过期的优先被淘汰
- noeviction:默认策略,当内存不足以容纳新写入数据时,新写入操作会报错
10、Redis 持久化
RDB 持久化:
- Redis Database Backup file(Redis数据备份文件)
- 每隔一段时间会将
数据
保存到磁盘中的备份文件中,在 redis.conf 配置文件中配置 - 执行条件:执行 save 命令,会阻塞;执行 bgsave 命令,异步执行;Redis 停机时;触发 RDB 条件时,在 redis.conf 配置文件中配置,如:
save 90 1
:90秒内,如果至少有1个 key 被修改,则执行 bgsave - 优缺点: 适合大规模的数据恢复场景,如备份,全量复制等。没办法做到实时持久化/秒级持久化;新老版本存在 RDB 格式兼容问题
AOF 持久化:
- Append Only File(追加文件)
- 每一个写
命令
都会记录在 AOF 文件,默认关闭,修改 redis.conf 配置文件来开启。AOF 每次写命令都会记录(频率一般设置为每秒),所以文件会记录一些没用的数据,而且占用会很大,所以需要文件重写来压缩持久化文件,auto-aof-rewrite-percentage 100
AOF 文件比上次文件增长超过 100% 则触发重写,auto-aof-rewrite-min-size 64mb
AOF 文件体积 64M 以上触发重写 - 优缺点: 数据的一致性和完整性更高。AOF 记录的内容越多,文件越大,数据恢复变慢
11、实现 Redis 的高可用
1)主从集群
搭建:
在多个服务器上启动多个 Redis 实例,要想让 B、C 实例成为 A 实例的从节点,需要在 B、C 实例的配置文件或者命令行中使用命令 slaveof <masterip> <masterport>
,A 就成为了主节点,可读可写,B、C 就成为了从节点,只可读;它们的数据会自动同步
全量同步:
- slave 节点请求增量同步,将自己的 Replication Id(是数据集的标记,id一致则说明是同一数据集。每一个 master 都有唯一的 replid,slave 则会继承 master 节点的 replid) 和 offset(偏移量,随着记录在 repl_baklog 中的数据增多而逐渐增大。slave 完成同步时也会记录当前同步的 offset。如果 slave 的 offset 小于 master 的 offset,说明 slave 数据落后于 master,需要更新) 发送过去
- master 节点判断 replid,发现不一致,拒绝增量同步,确定了是第一次请求
- master 将完整内存数据生成 RDB,发送 RDB 到 slave
- slave 清空本地数据,加载 master 的 RDB,并将继承 master 节点的 replid
- master 将 RDB 期间的命令记录在 repl_baklog,并持续将 log 中的命令发送给 slave
- slave 执行接收到的命令,保持与 master 之间的同步
增量同步:
- master 判断 slave 发送过来的 replid 与自己一致,然后就发送 repl_baklog 中两者的 offset 相差值的内容来进行增量同步
- repl_baklog 相当于是一个环形数组,当 slave 出现问题,导致两者的 offset 相差值大于了整个数组的长度,就必须进行全量同步了
优化主从集群:
- 在 master 中配置 repl-diskless-sync yes 启用无磁盘复制,避免全量同步时的磁盘 IO,但要求是网络带宽大,否则可能出现阻塞
- Redis 单节点上的内存占用不要太大,减少 RDB 导致的过多磁盘 IO
- 适当提高 repl_baklog 的大小,发现 slave 宕机时尽快实现故障恢复,尽可能避免全量同步
- 限制一个 master 上的 slave 节点数量,如果实在是太多 slave,则可以采用主-从-从链式结构,减少 master 压力
2)哨兵模式
作用:
- 监控:Sentinel 会不断检查您的 master 和 slave 是否按预期工作,每秒 ping 一下,未在规定时间内响应,则认为该实例主观下线,若超过指定数量(quorum)的 Sentinel 都认为该实例主观下线,则该实例客观下线
- 自动故障恢复:如果 master 故障(客观下线),Sentinel 会将一个 slave 选举为 master。当故障实例恢复后也以新的 master 为主。选举前先排除与 master 节点断开超过指定时间的 slave 节点,主要根据 offset 值,越大说明数据越新,优先级越高
- 通知:Sentinel 充当 Redis 客户端,当集群发生故障转移时,会将最新信息推送给 Redis 的客户端。Sentinel 给选中的 slave 节点发送
slaveof no one
命令,让该节点成为 master,然后给所有其它slave发送slaveof <新 master ip> <新 master port> 命令,让这些 slave 成为新 master 的从节点,最后,Sentinel 将故障节点标记为 slave,当故障节点恢复后会自动成为新的 master 的 slave 节点
搭建哨兵集群:
- 创建多个哨兵实例
- 为每个实例编写配置文件,指定监控的 master 节点的 ip、port、quorum
- 启动每一个实例,
redis-sentinel 配置文件路径
RedisTemplate 使用哨兵集群:
1.引入 spring-boot-starter-data-redis
依赖
2.配置 Redis 地址:spring:redis:sentinel:nodes: List<每个哨兵的ip地址:端口号>
3.配置读写分离:
@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){
//REPLICA _PREFERRED:优先从slave(replica)节点读取,所有的slave都不可用才读取master
return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}
3)分片集群
主从和哨兵可以解决高可用、高并发读的问题,分片集群进一步解决海量数据存储问题和高并发写的问题
搭建:
1.创建多个 Redis 实例
2.为每一个实例创建配置文件
3.启动每一个实例
4.使用命令创建集群:redis-cli --cluster create --cluster-replicas 1(每一个主节点的从节点数量) 192.168.150.101:7001 192.168.150.101:7002 192.168.150.101:7003 192.168.150.101:8001 192.168.150.101:8002 192.168.150.101:8003(根据计算,前三个会成为主节点,后三个会成为从节点)
散列插槽:
Redis 会把每一个 master 节点映射到 0~16383 共 16384 个插槽(hash slot)上。数据 key 是与插槽绑定的。Redis 会根据 key 的有效部分进行 Hash 取余计算插槽值来决定数据存放在哪个 master 上,有效部分是:key 中包含 “{}”,且 “{}” 中至少包含 1 个字符,“{}” 中的部分是有效部分;key 中不包含 “{}”,整个 key 都是有效部分。可以设置 {} 前缀来将一类数据保存到同一 master 上
集群伸缩:
1.启动一个 Redis 实例
2.添加实例到集群:redis-cli --cluster add-node 192.168.150.101:7004(自己的实例) 192.168.150.101:7001(通知给集群中的一个实例)
3.转移插槽,刚添加的实例是没有插槽的,redis-cli --cluster reshard 192.168.150.101:7004(自己的实例)
,然后根据选项输入指定实例 id 来转移指定数量的插槽
故障转移:
- 自动故障转移:当 一个master 宕机后,集群会自动选一个它的子节点来成为 master 节点
- 手动故障转移:利用
cluster failover
命令可以手动让集群中这个 slave 节点成为 master 节点,实现无感知的数据迁移
RedisTemplate 使用分片集群:
- 引入
spring-boot-starter-data-redis
依赖 - 配置 Redis 地址:
spring:redis:cluster:nodes: List<每个哨兵的ip地址:端口号>
- 配置读写分离:
@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){
//REPLICA _PREFERRED:优先从slave(replica)节点读取,所有的slave都不可用才读取master
return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}
12、使用过 Redis 分布式锁嘛
数据库实现:
乐观锁,多个线程去插入数据,谁插入成功谁就获取到锁
zookeeper 实现:
zookeeper 的结构类似的文件目录,多线程向 zookeeper 创建一个子目录(节点)只会有一个创建成功,利用此特点可以实现分布式锁,谁创建该结点成功谁就获得锁
Redis 实现:
set key value NX EX 失效时间
命令实现,setIfAbsent(key,value)
方法,只有当键不存在的时候才能设置成功。需要结合 Lua 脚本解决原子性问题。而且过期时间设置不好确定Redisson
实现,使用看门狗线程给使用中的锁续期,保证原子性,实现了 Lock 接口,List 接口
13、Redisson 原理
Redisson 使用:
- 引入
redisson-spring-boot-starter
依赖 - 在 yml 配置文件中配置 redisson 配置文件位置,然后引入配置文件
- 使用
RedissonClient
对象,getLock 方法设置锁获得 Lock 锁对象,然后锁对象进行上锁 lock(),释放锁 unlock
Redisson 原理:
只要线程加锁成功,就会启动一个 watch dog 看门狗,它是一个后台线程,会每隔 10 秒检查一下,如果线程还持有锁,那么就会不断的延长锁 key 的生存时间。因此,Redisson 就是解决了锁过期释放,业务没执行完问题
14、什么是 Redlock 算法
Redlock 算法解决的问题:
Redis 一般都是集群部署的,假设数据在主从同步过程,主节点挂了,如果线程一在 Redis 的 master 节点上拿到了锁,但是加锁的 key 还没同步到 slave 节点。恰好这时,master 节点发生故障,一个 slave 节点就会升级为 master 节点。线程二就可以获取同个 key 的锁,但线程一也已经拿到锁了,锁的安全性就得不到保障了,Redlock 算法就是解决这个问题的
Redlock 算法核心思想:
搞多个 Redis master 部署,以保证它们不会同时宕掉。并且这些 master 节点是完全相互独立的,相互之间不存在数据同步。同时,需要确保在这多个 master 实例上,是与在 Redis 单实例,使用相同方法来获取和释放锁
Redlock 算法核心步骤:
- 按顺序向多个 master 节点请求加锁
- 根据设置的超时时间来判断,是不是要跳过该 master 节点
- 如果大于一半的节点加锁成功,并且使用的时间小于锁的有效期,即可认定加锁成功
- 如果获取锁失败,解锁
15、MySQL 与 Redis 如何保证双写一致性
- 延时双删:强一致性。先删缓存,再修改数据库,因为有数据库的主从复制,所以延时一会在删除缓存。但是延时的时间不好控制,还是有脏数据风险
- 分布式锁:强一致性。使用加锁来防止意外情况,然后就可以正常同步数据。使用读写锁提高性能,代码中使用 redissonClient.getReadWriteLock 方法实现
- MQ 异步通知:最终一致性。依赖 MQ 的可靠性
- Canal 异步通知:最终一致性。伪装成从节点监听 binlog 日志
16、Redis 事务机制
Redis 通过 multi、exec、watch 等一组命令集合,来实现事务机制。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。简言之,Redis事务就是顺序性、一次性、排他性的执行一个队列中的一系列命令。执行事务的流程:开始事务(MULTI)、命令入队、执行事务(EXEC)、撤销事务(DISCARD )
17、Redis 的 Hash 冲突怎么办
- Redis 作为一个 K-V 的内存数据库,它使用用一张全局的哈希来保存所有的键值对。这张哈希表,有多个哈希桶组成,哈希桶中有 entry 元素,每一个 entry 元素保存了 key 和 value 指针,其中 *key 指向了实际的键,*value 指向了实际的值
- Redis 为了解决哈希冲突,采用了链式哈希。链式哈希是指同一个哈希桶中,多个元素用一个链表来保存,它们之间依次用指针连接。哈希冲突链上的元素只能通过指针逐一查找再操作
- 当往哈希表插入数据很多,冲突也会越多,冲突链表就会越长,那查询效率就会降低了。为了保持高效,Redis 会对哈希表做 rehash 操作,也就是增加哈希桶,减少冲突。为了 rehash 更高效,Redis 还默认使用了两个全局哈希表,一个用于当前使用,称为主哈希表,一个用于扩容,称为备用哈希表
18、Redis 底层,使用的什么协议
- RESP,英文全称是 Redis Serialization Protocol,它是专门为 Redis 设计的一套序列化协议。这个协议其实在 Redis 1.2 版本时就已经出现了,但是到了 Redis 2.0 才最终成为 Redis 通讯协议的标准
- RESP 主要有实现简单、解析速度快、可读性好等优点