Java 面试 - Redis

Redis

Redis 是基于键值对的非关系型数据库。Redis 拥有string、hash、list、set、zset等多种数据结构, redis具有惊人的读写性能, 其优秀的持久化机制是的它在断电和机械故障时也不会发生数据丢失, 可以用于热点数据存放, 还提供了键过期、发布订阅、食物、流水线、LUA脚本等多个高级功能。

1 Redis 数据结构

  • string: 最基本数据类型, 可以存放入二进制、序列化数据、JSON对象、图片等数据

    • 底层实现: SDS(Simple Dynamic String) - 动态字符串

      可修改字符串, 采用预分配冗余空间的方式减少内存的频繁分配。与Java中的ArrayList比较类似, 实质上也是在空间不足时触发扩容机制, 如果 SDS 值大小< 1M , 则增加一倍;反之如果>1M , 则当前空间加1M作为新的空间。
      在这里插入图片描述

      struct sdshdr{//记录buf数组中已使用字节的数量//等于SDS保存字符串的长度4byteint len;//记录 buf数组中未使用字节的数量 4 byteint free;//字节数组,用于保存字符串字节\0结尾的字符串占用了1bytechar buf[];
      }
      
  • list: 字符串列表, 按照插入的顺序排序, 元素可以重复, 底层由 链表 实现。

    • 底层实现: ZIPList| LinkedList(双向链表)

      当元素字符串的长度小于64字节而且元素个数小于512时,采用 zipList;否则采用likedList;

      • ZIPList - 压缩列表: 由连续内存块组成且用于存储小型有序集合或哈希集合的数据结构。主要参数包括: 整个列表占用字节数、偏移量、元素个数、内容列表、结束标志。 优点: 节省空间
        在这里插入图片描述

        struct ziplist<T> {int32 zlbytes; // 整个压缩列表占用字节数int32 zltail_offset; // 最后一个元素距离压缩列表起始位置的偏移量,用于快速定位到最后一个节点int16 zllength; // 元素个数T[] entries; // 元素内容列表,挨个挨个紧凑存储int8 zlend; // 标志压缩列表的结束,值恒为 0xFF
        }
        
  • hash: string 类型 field 和 value 的集合, 适合存放对象

    • 底层实现: ZIPList | HashTable

      当hash对象的键与值的长度都小于64字节时而且键值对的个数小于512个,采用zipList,其它情况,采用hashTable

      • ZIPLIST: 参考上述

      • HashTable - 哈希表

        ① 数组 + 链表 ②数组+红黑树(树化方便查找)

        根据Key value而直接进行访问的数据结构。它通过把关键码值映射到表中一个位置来访问记录(类似索引),以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

  • set: 无序不重复的集合

    • 底层实现: INTSet | HashTable

      当保存的元素都是整形数字,而且元素个数小于配置范围的时候,则使用intset,否则使用hash表。

      • INTSet - 整数集合

        可变长度的整型数组 - 基于整数数组来实现,并且具备长度可变、有序等特征, 包含: 编码方式、长度、内容等主要属性(可以选择不同位数的整数存储)。

        typedef struct intset {uint32_t encoding; /* 编码方式,支持存放16位、32位、64位整数 */uint32_t length;  /* 元素个数 */int8_t contents[];  /* 整数数组,保存集合数据 */
        } intset;
        
  • zset: 与 set 一样都是 String 类型元素的集合, 且不允许重复, 但 zset 每个元素都会关联一个分数, Redis通过分数来为集合汇总的成员进行从小到大的排序。

    • 底层实现: ZIPList| SKIPList

      • ZIPList: 参考上述

      • SKIPList:

        一种有序的数据结构,通过在每个节点维护多个指针,从而达到快速访问的目的。 优点: 实现简单、内存消耗少 缺点: 不适合范围查询

        跳跃表 - 跳跃表节点结构定义

        typedef struct zskiplist{// 表头节点和表尾节点struct zskiplist *header,*tail;// 表节点个数unsigned long length;// 表节点最大层数int level;
        }zskiplist;
        
        typedef struct zskiplistNode{// 层struct zskiplistLevel{// 前进指针struct zskiplistNode *forward;// 跨度unsigned int span;}level[];// 后退指针struct zskiplistNode *backward;// 分值double score;// 成员对象robj *robj;
        }zskiplistNode;
        
  • 四种特殊数据类型: 1)bitmap 2)hyperloglog 3)geo 4)stream

1) zset 与 set 的区别

  • set 无序, zset 有序

  • zset 底层使用压缩列表和跳跃列表( ziplist & skiplist )

    set 使用 INTSet 和 HashTable

2 Key 过期策略

  • 定期删除 - 过期 Key 保存在字典, 定期随机抽取20个Key, 删除其中过期的, 如果比例超过1/4, 重复删除步骤。

    redis 会将每个设置了过期时间的 key 放入到一个独立的字典中,以后会定期遍历这个字典来删除到期的 key。

    Redis 默认会每秒进行十次过期扫描(100ms一次),过期扫描不会遍历过期字典中所有的 key,而是采用了一种简单的贪心策略。

    1.从过期字典中随机 20 个 key;

    2.删除这 20 个 key 中已经过期的 key;

    3.如果过期的 key 比率超过 1/4,那就重复步骤 1;

    redis默认是每隔 100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。注意这里是随机抽取的。为什么要随机呢?你想一想假如 redis 存了几十万个 key ,每隔100ms就遍历所有的设置过期时间的 key 的话,就会给 CPU 带来很大的负载。

  • 惰性删除 - 访问时发现 Key 过期, 直接删除不返回任何值

    在客户端访问这个key的时候,redis对key的过期时间进行检查,如果过期了就立即删除,不会给你返回任何东西。

    定期删除可能会导致很多过期key到了时间并没有被删除掉。所以就有了惰性删除。假如你的过期 key,靠定期删除没有被删除掉,还停留在内存里,除非你的系统去查一下那个 key,才会被redis给删除掉。这就是所谓的惰性删除,即当你主动去查过期的key时,如果发现key过期了,就立即进行删除,不返回任何东西。

3 内存淘汰策略

数据的淘汰策略: 当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。

  • noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认策略。

  • volatile-TTL: 对设置了TTL的key,比较key的剩余TTL值,TTL越小越先被淘汰。

  • allkeys -RANDOM: 对全体key,随机进行淘汰。

  • volatile-RANDOM: 对设置了TTL的key,随机进行淘汰。

  • alkeys -LRU: 对全体key,基于LRU算法进行淘汰

  • volatile-LRU: 对设置了TTL的key,基于LRU算法进行淘汰

  • allkeys -LFU: 对全体key,基于LFU算法进行淘汰

  • volatile-LFU: 对设置了TTL的key,基于LFU算法进行淘汰

4 主从同步机制

  • 主从同步

    • 全量同步

      一般发生在第一次连接时, 原理为将当前数据写入到RDB文件后发送给从机读取到丛机的内存中。

    • 增量同步

      一般发生在第一次之后的链接时, 主机同步期间发生的数据变化会以命令的形式写入缓存中, 当校验到正确的从机ID时获取从机的偏移量,然后从偏移量记录的命令开始将未同步的数据操作命令发送给从机执行, 进而完成数据同步。


updating …

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android样本Repack重打包检测思路

1. 什么是Android样本重打包&#xff0c;为什么要检测重打包 &#xff08;1&#xff09;apk是zip&#xff0c;很容易做repack &#xff08;2&#xff09;repack后&#xff0c;被抄袭&#xff0c;redirect ad&#xff0c;或者插入malicious payloads &#xff08;3&#xff09;…

计算机网络 | TCP 三次握手四次挥手 |半关闭连接

本来是不愿意写的&#xff0c;可是在实际场景&#xff0c;对具体的描述标志还是模糊不清&#xff0c;基础不扎实&#xff0c;就得承认&#xff01;&#xff01;&#xff01; TCP 连接建立需要解决三大问题&#xff1a; 知道双方存在约定一些参数&#xff0c;如最大滑动窗口值、…

Java版电子招投标管理系统源码-电子招投标认证服务平台-权威认证

项目说明 随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大&#xff0c;公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境&#xff0c;最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&#xff0c;以及…

JavaScript Web APIs-01学习

复习&#xff1a; splice() 方法用于添加或删除数组中的元素。 **注意&#xff1a;**这种方法会改变原始数组。 删除数组&#xff1a; splice(起始位置&#xff0c; 删除的个数) 比如&#xff1a;1 let arr [red, green, blue] arr.splice(1,1) // 删除green元素 consol…

Java中转换流(InputStreamReader,OutputStreamWriter),打印流(PrintStream,PrintWriter)

转换流 InputStreamReader 和 OutputStreamWriter 是 Java 中用于字符流和字节流之间进行转换的转换流类。它们主要用于解决字符编码的问题&#xff0c;在字节流和字符流之间提供了桥梁&#xff0c;可以将字节流转换为字符流或将字符流转换为字节流。 InputStreamReader&#…

深度探索JavaScript中的原型链机制

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责…

在使用Vant组件库时,实现下拉刷新,只有在列表顶部才会刷新

场景 官方代码&#xff0c;是只要下拉就会刷新&#xff0c;但这并不是我们想要的&#xff0c;我们想要实现下拉刷新&#xff0c;只有在列表顶部才会刷新 解决 全局样式 .van-pull-refresh {height: calc(100vh - 100px) !important;overflow: auto !important; }结语 感谢…

电脑提示缺少d3dx9_43.dll的问题及5个解决方法

大家好&#xff01;今天&#xff0c;我将和大家分享一个电脑提示缺少d3dx9_43.dll的问题及其解决方法。这个问题可能会影响到我们在使用电脑时的一些功能&#xff0c;所以掌握这个解决方法对我们来说是非常有帮助的。 首先&#xff0c;我们来了解一下什么是d3dx9_43.dll。d3dx9…

Visual Studio软件_MSC_VER值(MSVC编译器版本)的获取方法

本文介绍查看Visual Studio软件_MSC_VER值的方法。 _MSC_VER是微软公司推出的C/C 编译器——MSVC编译器的一个内置宏&#xff0c;其值表示当前Visual Studio软件中MSVC编译器的具体版本。不同的Visual Studio软件版本对应着不同的MSVC编译器版本——无论是不同发布年份的版本&…

【iOS】Masonry的基本使用

文章目录 前言一、使用Masonry的原因二、约束的常识三、Masonry的简单使用四、Masonry的用例总结 前言 暑假安装了cocoapods&#xff0c;简单使用其调用了SVGKit&#xff0c;但是没有学习Masonry&#xff0c;特此总结博客记录Masonry的学习 一、使用Masonry的原因 Masonry是一…

泡泡玛特回应头部IP营收增速放缓:IP上市时间不固定

8月23日&#xff0c;针对今年上半年头部IP营收增速放缓问题&#xff0c;泡泡玛特&#xff08;09992.HK&#xff09;管理层在业绩会上解释称&#xff0c;每个IP上市时间并不固定&#xff0c;单从上半年看同比增长会有偏差&#xff0c;而随着下半年两个新系列的推出&#xff0c;全…

算法 -汉诺塔,哈夫曼编码

有三个柱子,分别为 from、buffer、to。需要将 from 上的圆盘全部移动到 to 上,并且要保证小圆盘始终在大圆盘上。 这是一个经典的递归问题,分为三步求解: ① 将 n-1 个圆盘从 from -> buffer ② 将 1 个圆盘从 from -> to ③ 将 n-1 个圆盘从 buffer -> to 如果…