【java面试题-Redis篇-2024】

news2024/11/27 22:22:29

##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 就成为了从节点,只可读;它们的数据会自动同步

全量同步:

  1. slave 节点请求增量同步,将自己的 Replication Id(是数据集的标记,id一致则说明是同一数据集。每一个 master 都有唯一的 replid,slave 则会继承 master 节点的 replid) 和 offset(偏移量,随着记录在 repl_baklog 中的数据增多而逐渐增大。slave 完成同步时也会记录当前同步的 offset。如果 slave 的 offset 小于 master 的 offset,说明 slave 数据落后于 master,需要更新) 发送过去
  2. master 节点判断 replid,发现不一致,拒绝增量同步,确定了是第一次请求
  3. master 将完整内存数据生成 RDB,发送 RDB 到 slave
  4. slave 清空本地数据,加载 master 的 RDB,并将继承 master 节点的 replid
  5. master 将 RDB 期间的命令记录在 repl_baklog,并持续将 log 中的命令发送给 slave
  6. slave 执行接收到的命令,保持与 master 之间的同步

增量同步:

  1. master 判断 slave 发送过来的 replid 与自己一致,然后就发送 repl_baklog 中两者的 offset 相差值的内容来进行增量同步
  2. 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 节点

搭建哨兵集群:

  1. 创建多个哨兵实例
  2. 为每个实例编写配置文件,指定监控的 master 节点的 ip、port、quorum
  3. 启动每一个实例,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 使用分片集群:

  1. 引入 spring-boot-starter-data-redis 依赖
  2. 配置 Redis 地址:spring:redis:cluster:nodes: List<每个哨兵的ip地址:端口号>
  3. 配置读写分离:
@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 使用:

  1. 引入 redisson-spring-boot-starter 依赖
  2. 在 yml 配置文件中配置 redisson 配置文件位置,然后引入配置文件
  3. 使用 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 主要有实现简单、解析速度快、可读性好等优点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1577125.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝桥杯考前复习三

1.约数个数 由乘法原理可以得出&#xff1a; import java.util.*; public class Main{static int mod (int)1e9 7;public static void main(String[] args){Map<Integer,Integer> map new HashMap<>(); //创建一个哈希表Scanner scan new Scanner(System.in);i…

只需三步,本地打造自己的AI个人专属知识库

一、引言 本文会手把手教你如何部署本地大模型以及搭建个人知识库&#xff0c;使用到的工具和软件有 OllamaOpen WebUIDockerAnythingLLM 本文主要分享三点 如何用Ollama在本地运行大模型使用现代Web UI和本地大模型"聊天"如何打造完全本地化的知识库&#xff1a…

突破视野限制 | 利用4D雷达进行SLAM的循环闭合检测

作者&#xff1a;小柠檬 | 来源&#xff1a;3DCV 在公众号「3DCV」后台&#xff0c;回复「原论文」可获取论文pdf 添加微信&#xff1a;dddvision&#xff0c;备注&#xff1a;3D高斯&#xff0c;拉你入群。文末附行业细分群 详细内容请关注3DCV 3D视觉精品课程&#xff1a;…

14届蓝桥杯 C/C++ B组 T7 子串简写 (字符串)

采用存储目标字符下标的方法&#xff0c;此题的想法比较新奇&#xff0c;故予以记录。 存好下标之后&#xff0c;可以先定位好启始的字符&#xff0c;然后去搜结尾字符符合长度k并且最靠近启始字符的下标&#xff0c;找到之后可以直接取到这个下标之后的所有下标&#xff0c;因…

4.6java学习总结

内部类(补充) 局部内部类 如果在外界定义会检测不到你所定义的局部内部类,直接报错. public class Main {public static void print(int age,int b){class person{int age;public person(int age) {this.age age;}void show(){System.out.println("内部类输出: "a…

探索Flutter混淆在提高应用安全性方面的作用

在移动应用开发中&#xff0c;保护应用代码安全至关重要。Flutter 提供了简单易用的混淆工具&#xff0c;帮助开发者在构建 release 版本应用时有效保护代码。本文将介绍如何在 Flutter 应用中使用混淆&#xff0c;并提供了相关的操作步骤和注意事项。 &#x1f4dd; 摘要 本…

ESP32调试笔记

目录 基于Thonny和micropythonESP32-CAM开发板无法连接Thonnyesp32cam局域网图传esp32代码上位机代码 基于Thonny和micropython ESP32-CAM开发板无法连接Thonny esp32cam有两个模式&#xff1a;下载模式、运行模式 两种模式的接线不同 IO0 短路 GND ! 正是因为两种模式接线…

LeetCode第十五题:三数之和【15/1000 python】

&#x1f464;作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 LeetCode解锁1000题: 打怪升级之旅htt…

第十二届蓝桥杯大赛软件赛省赛C/C++大学B组

第十二届蓝桥杯大赛软件赛省赛C/C 大学 B 组 文章目录 第十二届蓝桥杯大赛软件赛省赛C/C 大学 B 组1、空间2、卡片3、直线4、货物摆放5、路径6、时间显示7、砝码称重8、杨辉三角形9、双向排序10、括号序列 1、空间 1MB 1024KB 1KB 1024byte 1byte8bit // cout<<"2…

软考-系统集成项目管理中级-新一代信息技术

本章历年考题分值统计 本章重点常考知识点汇总清单(掌握部分可直接理解记忆) 本章历年考题及答案解析 32、2019 年上半年第 23 题 云计算通过网络提供可动态伸缩的廉价计算能力&#xff0c;(23)不属于云计算的特点。 A.虚拟化 B.高可扩展性 C.按需服务 D.优化本地存储 【参考…

软件测试经典面试题:如何测微信的朋友圈?

这是一道非常经典的面试题&#xff0c;相信很多小伙伴在面试中都被面试官问到过这个问题&#xff0c;想要回答好这个面试题&#xff0c;我们首先要搞清楚面试官在考察候选者什么方向测试技能。其实不难猜出&#xff0c;面试官主要是想考察候选者测试用例设计能力。一般会从以下…

【游戏逆向】逆向基础之发包函数和线程发包

网络游戏是需要服务器的&#xff0c;这样才能玩家之间&#xff0c;服务器和玩家之间进行通信。 所以&#xff0c;我们的很多动作&#xff0c;都是要向服务器发包的&#xff0c;那么我们只要能够锁定正确的发包函数&#xff0c;就能很容易的通过调用关系找到该动作的函数&…

Springboot整合tess4j+tesseract实现OCR(文字识别),最新教程!

前言 不用引入什么dll&#xff0c;以及各种乱七八糟的东西。不废话&#xff0c;直接开始教程&#xff01;没有过多讲解里面的知识点&#xff0c;如有需要详细了解请加Qq:1101165230 1、Linux下安装与使用 1.1 安装tesseract&#xff08;复制粘贴敲回车&#xff0c;中间输入Y&…

王权与自由国际服测试资格申请 王权与自由steam国际服预约教程

《王权与自由》是一款由《剑灵》开发商NCsoft公开的旗下大型多人MMORPG新作游戏作品。攻城战&#xff0c;这是游戏中的一个重要玩法&#xff0c;主要分为攻城方和防守方。攻城方需要占领外城的遗址&#xff0c;并利用高轮&#xff08;包括碎石机、跳跃者和战斗航母&#xff09;…

JavaEE初阶之单例模式详解

目录 题外话 正题 单例模式 概念 优点 缺点 饿汉式单例模式 代码及详解 懒汉式单例模式 代码及详解 小结 题外话 昨天爬山去了,回来吃了个烧烤有点累,昨天旷了一天,每周稳定发个五篇文章是没什么太大问题的 正题 单例模式 概念 是一种常见的软件设计模式,确保一个类…

2024/4/2—力扣—栈的最小值

代码实现&#xff1a; typedef struct node {int val;struct node *next; } Node;typedef struct {struct node *top;int min; } MinStack;/** initialize your data structure here. */MinStack* minStackCreate() {MinStack *obj malloc(sizeof(*obj));obj->top NULL;ob…

ArcGIS Server 安装教程

​​​​​​​ 一、环境与文件准备 1.软件环境 已安装arcgis Desktop 10.2 2.安装及授权文件 二、安装步骤 1.下载安装包和授权文件&#xff0c;解压后打开ArcGIS Server10.2文件夹&#xff0c;打开ESRI.exe。 2.点击ArcGIS for Server后的Setup&#xff0c;开始安装。 3.…

scratch绘制六芒星图 2024年3月中国电子学会 图形化编程 scratch编程等级考试二级真题和答案解析

目录 scratch绘制六芒星图 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、实现流程 1、案例分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 …

[C++][算法基础]模拟堆(堆)

维护一个集合&#xff0c;初始时集合为空&#xff0c;支持如下几种操作&#xff1a; I x&#xff0c;插入一个数 x&#xff1b;PM&#xff0c;输出当前集合中的最小值&#xff1b;DM&#xff0c;删除当前集合中的最小值&#xff08;数据保证此时的最小值唯一&#xff09;&…

基于springboot的充电桩管理系统 (含源码+sql+视频导入教程+文档+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于springboot的充电桩管理系统1拥有三种角色&#xff1a;管理员、用户和维修人员 管理员&#xff1a;用户管理、充电桩管理、报修管理、类别管理、充电常识管理等 维修人员&#xff…