Redis 篇-深入了解 Redis 五种数据类型和底层数据结构(SDS、Intset、Dict、ZipList、SkipList、QuickList)

news2024/11/23 8:23:16

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

文章目录

        1.0 Redis 底层数据结构

        1.1 Redis 数据结构 - 动态字符串 SDS

        1.2 Redis 数据结构 - Intset

        1.3 Redis 数据结构 - Dict

        1.3.1 Dict 的渐进式 rehash

        1.4 Redis 数据结构 - ZipList

        1.5 Redis 数据结构 - QuickList

        1.6 Redis 数据结构 - SkipList

        1.7 Redis 数据结构 - RedisObject

        2.0 数据类型

        2.1 数据类型 - String

        2.2 数据类型 - List

        2.3 数据类型 - Set

        2.4 数据类型 - ZSet

        2.5 数据类型 - Hash


        1.0 Redis 底层数据结构

        在 Redis 的底层实现中,除了高层的抽象数据结构(如字符串、哈希、列表、集合等)之外,还有一些更底层的原始数据结构。

        1.1 Redis 数据结构 - 动态字符串 SDS

        简单动态字符串,简称 SDS 。

        Redis 是 c 语言实现的,其中 SDS 是一个结构体,结构如下:

        字段解析:

        1)uint8_t len:表示 buf 字符数组中已经保存的字符个数,因为一个字符占一个字节,也可以表示已保存的字节数,且不包含结束标识: "\0" 。uint8_t 代表 len 占用了 8 个比特位,也就是一个字节,因此表示 buf 字符数组的最大容量为 2^8 。

        2)uint8_t alloc:表示 buf 字符数组申请的总的字节数,同理,且不包含结束标识:"\0" 。

        3)unsigned char flags:表示不同 SDS 的类型,用来控制 SDS 的头大小,一共有五种类型。不同的 SDS 类型,可以表示 buf 的容量大小不同。

        4)char buf[]:字符数组,存放真实数据的容器。 

举个例子:

        一个包含字符串 "name" 的 SDS 结构体如下:

SDS 之所以叫做动态字符串,是因为它具备动态扩容的能力:

        1)如果新字符串小于 1 M,则新空间为扩展后字符串长度的两倍 + 1 。

        2)如果新字符串大于 1 M,则新空间为扩展后字符串长度 + 1M + 1,称为内存预分配。

举个例子:

        一个原本的字符串数组为 "hi" 的 SDS 结构为:

        接着,假如追加一段字符串 ",Amy",这里首先会申请新的内存空间:

        由于 "hi,Amy" 加起来的大小为 6 个字节,小于 1M,因此需要扩展至 13 个字节大小即可。

        新的字符数组的 SDS 结构如下:

        关于 alloc 为什么不是 13 个字节呢?

        这是因为 alloc 表示申请大小不包含结束标识 "\0",实际上,是扩展至 13 个字节大小。

动态字符串 SDS 的优点:

        1)获取字符串长度的时间复杂度为 O(1) 。

        2)支持动态扩容。

        3)由于支持内存预分配机制,因此减少内存分配次数。

        4)由于表示了字符数组的总长度,因此明确结束标识的具体位置,所以二进制安全。

        1.2 Redis 数据结构 - Intset

        IntSet 是 Redis 中 set 集合的一种实现方式,基于整数数组来实现,并且具备长度可变、有序等特征。

IntSet 结构如下:

字段解析:

        1)uint32_t encoding:编码方式,支持存放 16、32、64 位整数。该字段的目的是规定在整数数组中的每一个数据的范围大小。

        2)uint32_t length:元素个数,表示的范围由 encoding 编码方式决定。

        3)int8_t cotents[]:具体存放的数据,每一个数据的范围大小都是由 encoding 编码方式来决定的。

        为了方便查找,Redis 会将 intset 中所有的整数按照升序依次保存在 contents 数组中,结构如下:

        现在数组中每个数字都是在两个字节的范围内,因此采用的编码方式是 INTSET_ENC_INT16,每部分占用的字节大小为:

        encoding:固定占用 4 个字节。

        length:固定占用 4 个字节。

        contents:2 字节 * 3 = 6 个字节。

IntSet 升级:

        当要插入的数字大小当前整数所表示的范围时,intset 会自动升级编码方式到合适大小。

        现在,假设有一个 intset,元素为:{5,10,20},采用的编码是 INTSET_ENC_INT16,则每个整数占 2 个字节,接着向其中添加一个数字 50000,这个数字超出了 int16_t 的表示范围,intset 会自动升级编码方式到合适的大小,流程如下:

        1)升级编码为 INTSET_ENC_INT32,每个整数占 4 个字节,并按照新的的编码方式及元素个数扩容数组。

        2)倒叙依次将数组中的元素拷贝到扩容后的正确位置。

        3)将待添加的元素放入数组末尾。

        4)最后,将 intset 的 encoding 属性改为 INTSET_ENC_INT32,将 length 属性改为 4 。

IntSet 可以看做是特殊的整数数组,具备的特点:
        1)Redis 会确保 Intset 中的元素唯一、有序。

        2)具备类型升级机制,可以节省内存空间。

        3)底层采用二分查找方式来查询。

        1.3 Redis 数据结构 - Dict

        Redis 是一个键值型的数据库,可以根据键实现快速的增删改查。而键与值的映射关系正是通过 Dict 来实现的。

        Dict 由三部分组成,分别是:哈希表(DictHashTable)、哈希节点(DictEntry)、字典(Dict)。

哈希表和哈希节点的结构体:

        哈希表由数组和链表组成,而链表节点则为哈希点。

字段解析:

        1)dictEntry **table:表示指针指向哈希表的地址。

        2)unsigned long size:哈希表大小,哈希表的大小总是设置为: 2^n 次方,最小的哈希表为 4 。

        3)unsigned long sizemask:哈希表大小的掩码,总等于 size - 1,用来计算哈希点具体存放在数组的哪一个索引下的链表中。

        当向 Dict 添加键值对时,Redis 首先根据 key 计算出 hash 值,然后利用 hash 值 & sizemask 来计算元素应该存储数组中的哪个索引位置,最后再进行头插链表的方式存储起来。

        4)unsigned long used:哈希节点的个数。

        5)void *key:指向 key 的地址。

        6)union{} value:联合体,表示 value 的类型。

        7)struct dictEntry *next:指向下一个节点。

字典的结构体:

        字段解析:

        1)dictType *type:dict 类型,内置不同的 hash 函数。不用太在意该字段,了解即可。

        2)void *privdata:私有数据,在做特殊 hash 运算时用。不用太在意该字段,了解即可。

        3)dictht ht[2]:一个 Dict 包含两个哈希表,其中一个是当前数据,另一个一般是空,rehash 时使用。在扩容或者收缩数组大小会使用该字段。

        4)long rehashidx:rehash 的进度,-1 表示未进行。

        5)int16_t pauserehash:rehash 是否暂停,1 则暂停,0 则继续。

最终的结构:

        1.3.1 Dict 的渐进式 rehash

        Dict 中的 HashTable 就是数组结合单向链表的实现,当集合中元素较多时,必然导致哈希冲突增多,链表过长,则查询效率会大大降低。

        负载因子:LoadFactor = used / size ;

        Dict 在每次新增键值对时都会检查负载因子,满足以下两种情况时会触发哈希表扩容:

        1)哈希表的 LoadFactor >= 1,并且服务器没有执行 BGSAVE 或者 BGREWRITEAOF 等后台进程。

        2)哈希表的 LoadFactor > 5 。

        Dict 除了扩容以外,每次删除元素时,也会对负载因子做检查,当 LoadFactor < 0.1 时,会做哈希表收缩。

        不管是扩容还是收缩,必定会创建新的哈希表,导致哈希表的 size 和 sizemask 变化,而 key 的查询与 sizemask 有关。因此必须对哈希表中的每一个 key 进行重新计算索引,插入新的哈希表,这个过程为 rehash,过程如下:

        1)计算新 hash 表的 realeSize,值取决于当前要做的是扩容还是收缩:

        如果是扩容,则新 size 为第一个大于等于 dict.ht[0].used + 1 的 2^n。

        如果是收缩,则新 size 为第一个大于等于 dict.ht[1].used 的 2^n(不得小于 4)

        2)按照新的 realeSize 申请内存空间,创建 dictht,并赋值给 dict.ht[1]。

        3)设置 dict.rehashidx = 0,标示开始 rehash 。

        4)每次执行新增、查询、修改、删除操作时,都检查一下 dict.rehashidx 是否大于 -1,如果是则将 dict.ht[0].table[rehashidx] 的 entry 链表 rehash 到 dict.ht[1],并且将 rehashidx++ 。直至 dict.ht[0] 的所有数据都 rehash 到 dict.ht[1] 中。

        5)将 dict.ht[1] 赋值给 dict.ht[0],给 dict.ht[1] 初始化为空哈希表,释放原来的 dict.ht[0] 的内存。

        6)将 rehashidx 赋值为 -1,代表 rehash 结束。

        7)在 rehash 过程中,新增操作,则直接写入 ht[1],查询、修改和删除会在 dict.ht[0] 和 dict.ht[1] 依次查找并执行。这样可以确保 ht[0] 的数据只减不增,随着 rehash 最终为空。

最终的结构:

        1.4 Redis 数据结构 - ZipList

        ZipList 是一种特殊的 "双端链表",由一系列特殊的编码连续内存块组成。可以在任意一端进行压入/弹出操作,并且该操作的时间操作复杂度为:O(1) 。

        字段解析:

        1)zlbytes:4 个字节,记录整个压缩列表占用的内存字节数。

        2)zltail:4 个字节,记录压缩列表表尾节点距离压缩列表的起始地址有多少字节,通过这个偏移量,可以确定表尾节点的地址。

        3)zllen:2 个字节,记录了压缩列表包含的节点数量。最大值为 UINT16_MAX(65534),如果超过这个值,此处会记录为 65535,但节点的真实数量需要遍历整个压缩列表才能计算得出。

        4)entry:长度不定,压缩列表包含的各个节点,节点的长度由节点保存的内容决定。

        5)zlend:1 个字节,特殊值 0xFF(十进制 255),用于标记压缩列表的末端。

        ZipList 中的 entry 并不像普通链表那样记录前后节点的指针,因为记录两个指针要占用 16 个字节,浪费内存。而是采用如下结构:

字段解析:

        1)previous_entry_length:前一节点的长度,占 1 个或者 5 个字节:

        如果前一节点的长度小于 254 字节,则采用 1 个字节来保存这个长度值。

        如果前一节点的长度大于 254 字节,则采用 5 个字节来保存这个长度值,第一个字节为 0xfe,后四个字节才是真实长度数据。

        2)encoding:编码属性,记录 content 的数据类型(字符串还是整数)以及长度,占用 1 个、2 个或者 5 个字节。

        编码分为字符串和整数两种:

        字符串:如果 encoding 是以 "00"、"01" 或者 "10" 开头,则证明 content 是字符串;

举个例子:

        整数:如果 encoding 是以 "11" 开始,则证明 content 是整数,且 encoding 固定只占用 1 个字节。

举个例子:

        3)contents:负责保存节点的数据,可以是字符串或者整数。

ZipList 特征:

        1)压缩列表的可以看做一种连续内存空间的"双向链表"。

        2)列表的节点之间不是通过指针连接,而是记录上一个节点和本节点长度来寻址,内存占用较低。

        3)如果列表数据过多,导致链表过长,可能影响查询性能。

        4)增或删较大数据时有可能发生连续更行问题。

        1.5 Redis 数据结构 - QuickList

        ZipList 虽然节省内存,但申请内存必须是连续空间,如果内存占用较多,申请内存效率很低,该怎么办呢?

        这就不得不引入新的数据结构 QuickList,它是一个双端链表,只不过链表中的每个节点都是一个 ZipList,结构如下:

        1)为了避免 QuickList 中的每个 ZipList 中 entry 过多,Redis 提供了一个配置项:list-max-ziplist-size 来限制。

        如果值为正,则代表 ZipList 的允许的 entry 个数的最大值。

        如果值为负,则代表 ZipList 的最大内存大小,分五种情况:

        -1:每个 ZipList 的内存占用不能超过 4 kb;

        -2:每个 ZipList 的内存占用不能超过 8 kb;

        -3:每个 ZipList 的内存占用不能超过 16 kb;

        -4:每个 ZipList 的内存占用不能超过 32 kb;

        -5:每个 ZipList 的内存占用不能超过 64 kb;

其默认值为:-2

        2)除了控制 ZipList 的大小,QuickList 还可以对节点的 ZipList 做压缩。通过配置项 list-compress-depth 来控制。因为链表一般都是从首尾访问较多,所以首尾是不压缩的。

        0:特殊值,代表不压缩。

        1:标示 QuickList 的首尾各有 1 个节点不压缩,中间节点压缩。

        2:标示 QuickList 的首尾各有 2 个节点不压缩,中间节点压缩。

        以此类推......

        默认值是 0 ,不压缩节点。

QuickList 与 QuickListNode 的结构源码:

结构如下:

QuickList 的特点:

        1)是一个节点为 ZipList 的双端链表

        2)节点采用 ZipList,解决了传统链表的内存占用问题。

        3)控制了 ZipList 大小,解决连续内存空间申请效率问题。

        4)中间节点可以压缩,进一步节省内存。

        1.6 Redis 数据结构 - SkipList

        首先是链表,但与传统链表相比有以下差异:

        1)元素按照升序排序存储。

        2)节点可能包含多个指针,指针跨度不同。

在跳表中查找目标数据的步骤:

        1)初始化指针:从跳表的最高层的头节点开始,初始化一个指针(通常称为 current)。

        2)向右移动:在当前层中,检查 current 节点的下一个节点的值。如果这个值小于目标值,则将 current 指针移动到下一个节点。

        3)找到合适的位置:如果下一个节点的值大于或等于目标值,或者已经到达当前层的末尾,则停止此层的移动。

        4)向下移动:如果当前层已经达到目标值或找到了更大的值,改变层级,将 current 指针向下移动到下一层。如果目标值小于当前层的下一个节点的值, 则在这一层的当前节点停止查找,进入下一层按步骤 2 进行查找。

        5)重复步骤:重复步骤 2 到步骤 4,直到找到目标值或到达底层。如果找到了目标值,则查找成功;

        如果到达底层且没有找到目标值:

        在底层,检查当前节点的值。

        如果当前节点的值等于目标值,则查找成功。

        如果当前节点的值小于目标值,继续移动到下一个节点。

        如果当前节点的值大于目标值,停止查找。

SkipList 结构源码:

SkipList 结构:

SkipList 的特点:

        1)跳跃表是一个双向链表,每一个节点都包含 score 和 ele 值。

        2)节点按照 score 值排序,score 值一样则按照 ele 字典排序。

        3)每一个节点都快包含多层指针,层数是 1 到 32 之间的随机数。

        4)不同层指针到下一个节点的跨度不同,层级越高,跨度越大。

        5)增删改查效率与红黑树基本一致,实现却更简单。

        1.7 Redis 数据结构 - RedisObject

        Redis 中的任意数据类型的键和值都会被封装为一个 RedisObject,也叫做 Redis 对象,源码如下:

字段解析:

        1)unsigned type:对象类型,可以是 string、hash、list、set、zset,占用 4 个 bit 位。

        2)unsigned encoding:底层编码方式,共有 11 种,占 4 个 bit 位。

        3)int refcount:对象引用计数器,计数器为 0 则说明对象无人引用,可以被回收。

        4)void *ptr:指针,指向存放实际数据的空间。

        5)unsigned lru:lru 表示该对象最后一次被访问的时间,其占用 24 个 bit 位。便于判断空闲时间太久的 key 。

        Redis 中会根据存储的数据类型不同,选择不同的编码方式。每种数据类型的使用的编码方式如下:

        2.0 数据类型

        常见的五种数据类型:String、List、set、zset、hash,以下介绍这五种的数据类型,底层用到的数据结构:

        2.1 数据类型 - String

        String 是 Redis 中最常见的数据存储类型:

        1)其基本编码方式是 RAW,基于简单动态字符串(SDS)实现,存储上限为 512 mb 。

结构如下:

        2)如果存储的 SDS 长度小于 44 字节,则会采用 EMBSTR 编码,此时 object head 与 SDS 是一段连续空间。申请内存时只需要调用一次内存分配函数,效率更高。

结构如下:

        3)如果存储的字符串是整数值,并且大小在 LONG_MAX 范围内,则会采用 INT 编码:直接将数据保存在 RedisObject 的 ptr 指针位置(刚刚好 8 字节),不再需要 SDS 了。

结构如下:

        2.2 数据类型 - List

        Redis 的 List 结构类似一个双端链表,可以从首尾操作列表中的元素:

        在 3.2 版本之前,Redis 采用 ZipList 和 LinkedList 来实现 List,当元素数量小于 512 并且元素大小小于 64 字节时采用 ZipList 编码,超过则采用 LinkedList 编码。

        在 3.2 版本之后,Redis 统一采用 QuickList 来实现 List:

整体结构:

        2.3 数据类型 - Set

        Set 是 Redis 中的单列集合,满足下列特点:

        1)不保证有序性

        2)保证元素唯一(可以判断元素是否存在)

        3)求交集、并集、差集

因此:

        如果为了查询效率和唯一性,set 采用 HT 编码(Dict)。Dict 中的 key 用来存储元素,value 统一为 null 。

结构如下:

        如果存储的所有数据都是整数,并且元素数量不超过 set-max-intset-entries 时,Set 会采用 IntSet 编码,以节省内存。

结构如下:

 相关的源码:

        2.4 数据类型 - ZSet

        ZSet 也就是 SortedSet,其中每一个元素都需要指定一个 score 值和 member 值。

        其特点:可以根据 score 值排序、member 必须唯一、可以根据 member 查询分数。

因此:

        zset 底层数据结构必须满足键值存储、键必须唯一,可排序:

        1)SkipList:可以排序,并且同时存储 score 和 ele 值(member)

        2)HT(Dict):可以键值存储,并且可以根据 key 找 value

源码如下:

整体结构:

        当元素数量不多时,HT 和 SkipList 的优势不明显,而且更耗内存。因此 zset 还会采用 ZipList 结构来节省内存,不过需要同时满足两个条件:

        1)元素数量小于 zset_max_ziplist_entries,默认值 128

        2)每个元素都小于 zset_max_ziplist_value 字节,默认值 64

源码如下:

        思考:ziplist 本身没有排序功能,而且没有键值对的概念,因此需要有 zset 通过编码实现:

        1)ZipList 是连续内存,因此 score 和 element 是紧挨在一起的两个 entry,element 在前,score 在后。

        2)score 越小越接近队首,score 越大越接近队尾,按照 score 值升序排序。

整体结构如下:

        2.5 数据类型 - Hash

        Hash 结构与 Redis 中的 Zset 非常类似:都是键值存储、都要求根据键获取值、键必须唯一。

因此:

        Hash 结构默认采用 ZipList 编码,用以节省内存。ZipList 中相邻的两个 entry 分别保存 field 和 value 。

结构如下:

        当数据量较大,Hash 结构会转为 HT 编码,也就是 Dict,触发条件有两个:

        1)ZipList 中的元素数量超过了 hash-max-ziplist-entries(默认 512)

        2)ZipList 的任意 entry 大小超过了 hash-max-ziplist-value(默认 64 字节)

结构如下:

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

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

相关文章

记录-java web 生成并下载zip文件

java生成zip文件&#xff0c;zip文件分两种&#xff1a;一种是包含文件夹、一种是不包含文件夹 生成zip文件的方式 ZipOutputStream zipOutputStream new ZipOutputStream(response.getOutputStream());// 文件夹名称String folder "download/";ZipEntry ze new Z…

测试必存!12种网站崩溃的原因及排查方法!

网站崩溃是研发团队最怕看到的情况&#xff0c;但是由于种种原因却时常出现&#xff0c;作为测试人员&#xff0c;我们更应该比一般人了解网站崩溃的原因及排查方法&#xff0c;这是我们测试工作的重要一环。 接下来我就谈谈12种常见的网站崩溃原因以及如何跟踪和解决它们。 你…

《CUDA编程》2.CUDA中的线程组织

0 来自GPU的hello world 在visua studio 中新建一个CUDA runtime项目&#xff0c;然后把kernel.cu中的代码删掉&#xff0c;输入以下代码 #include"cuda_runtime.h" #include"device_launch_parameters.h"#include<stdio.h>__global__ void hello_…

VM ware的安装——个人使用

VM ware的安装 Workstation 和 Fusion 对个人使用完全免费&#xff0c;企业许可转向订阅 如果没有官方账号需要注册一个 选择个人下载&#xff0c;会跳转到下一个页面 要勾选同意&#xff0c;才能下载 点击下载之后还会跳转到填写地址的页面&#xff0c;填写完同意后&#x…

合宙LuatOS应用,与时间相关那些事

合宙嵌入式操作系统LuatOS——在蜂窝物联网模组上推出开源二次开发框架&#xff0c;功能齐全性能稳定&#xff0c;可大幅度降低用户的研发成本和研发周期。 在LuatOS中&#xff0c;获取时间函数用得最多的就是os.time()函数了。接下来&#xff0c;我会讲一些与这个函数以及其他…

美团外卖霸王餐系统有哪些优势?如何选择?

外卖霸王餐系统是一种流行的营销策略&#xff0c;旨在通过提供免费或优惠的餐食来吸引新顾客和提升品牌知名度。美团外卖平台本身拥有巨大的流量&#xff0c;美团霸王餐作为美团外卖平台推出的营销服务&#xff0c;能够充分利用这一流量优势。商家在平台上发布霸王餐活动信息&a…

美业门店怎么提升业绩?连锁美业门店管理系统收银系统拓客系统源码

美业门店想要提升业绩&#xff0c;需要考虑多方面的因素&#xff0c;并采取综合性的方法。以下是一些可以考虑的因素和建议&#xff1a; 产品与服务优化&#xff1a; 提供高质量的美容产品和服务&#xff0c;确保顾客满意度。不断更新产品线&#xff0c;引入新的时尚趋势&#…

Ansible流程控制-条件_循环_错误处理_包含导入_块异常处理

文章目录 Ansible流程控制介绍1. 条件判断2. 循环3. 循环控制4. 错误处理5. 包含和导入6. 块和异常处理7. 角色的流程控制*include_tasks、import_tasks_include之间的区别 条件语句再细说且、或、非、是模糊条件when指令的详细使用方法 循环语句再细说如何使用使用item变量结合…

应用targetSdkVersion升级指导

应用targetSdkVersion升级指导 应电信终端产业协会&#xff08;TAF&#xff09;发布的《移动应用软件高 API 等级预置与分发自律公约》&#xff08;以下简称《公约》&#xff09;要求&#xff1a;截止到2019年5月1日所有新发布的应用 API 必须为26或更高&#xff0c;2019年8月…

What is the OpenAI Chat Completion API tools/functions property format?

题意&#xff1a;OpenAI 聊天完成 API 的工具/函数属性格式是什么 问题背景&#xff1a; Is there any clear documentation on the format of OpenAIs Chat Completion API tools/functions object format? I understand its JSON, but there appear to be underlying requi…

tauri开发软件中,使用tauri自带的api用浏览器打开指定的url链接

有能力的可以看官方文档&#xff1a;shell | Tauri Apps 就是使用这个api来打开指定的url链接&#xff0c;要在tauri.config.json中配置打开这个api&#xff1a; 然后在前端页面中导入使用&#xff1a; import { open } from tauri-apps/api/shell; // opens the given URL o…

Cpp类和对象(下)(6)

文章目录 前言一、初始化列表概念使用注意实际运用explicit关键字初始化列表的总结 二、static成员static成员的概念static成员的特性static的一个实用场景 三、友元友元函数友元类 四、内部类概念特性 五、匿名对象六、再次理解封装和面向对象总结 前言 Hello&#xff0c;本篇…

redis学习(013 实战:黑马点评:优惠券秒杀——超卖问题解决方案)

黑马程序员Redis入门到实战教程&#xff0c;深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目 总时长 42:48:00 共175P 此文章包含第52p-第p53的内容 文章目录 问题演示使用jmeter测试两百个并发请求 超卖的原因分析解决方案 加锁悲观锁介绍乐观锁介绍乐观锁…

XXL-Job 监控消息队列消息数量预警

1、什么是Basic Authentication认证 Basic Authentication 是一种常用的 HTTP 认证机制&#xff0c;用于保护 Web 资源免受未授权访问。在这种认证方式中&#xff0c;客户端&#xff08;通常是浏览器&#xff09;需要在 HTTP 请求头中提供用户凭据&#xff08;通常是用户名和密…

Leetcode 最小覆盖子串

解题思路&#xff1a; 哈希表存储字符频率&#xff1a;首先统计字符串 t 中每个字符出现的次数。滑动窗口&#xff1a;用两个指针 left 和 right 来标记当前窗口的左右边界&#xff0c;不断右移 right&#xff0c;直到包含了所有 t 中的字符。然后尝试右移 left&#xff0c;缩…

python爬虫/引用requests/基本使用

1.安装requests 进入控制台使用该命令安装requests pip3 install requests 2.对网站使用get请求 这里用对网站进行get请求&#xff0c;然后打印。 import requests //引用requestsresponse requests.get(urlhttps://www.bilibili.com/)print(response.text) 3.对网站使用…

2024全国研究生数学建模竞赛(数学建模研赛)ABCDEF题深度建模+全解全析+完整文章

全国研究生数学建模竞赛&#xff08;数学建模研赛&#xff09;于9月21日8时正式开赛&#xff0c;赛程4天半&#xff0c;咱这边会在开赛后第一时间给出对今年的6道赛题的评价、分析和解答。包括ABCDEF题深度建模全解全析完整文章&#xff0c;详情可以点击底部的卡片来获取哦。 …

座椅空置状态检测系统源码分享

座椅空置状态检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

大模型之基准测试集(Benchmark)-给通义千问2.0做测评的10个权威测基准测评集

引言 在去年(2023)云栖大会上&#xff0c;阿里云正式发布千亿级参数大模型通义千问2.0。据现场介绍&#xff0c;在10个权威测评中&#xff0c;通义千问2.0综合性能超过GPT-3.5&#xff0c;正在加速追赶GPT-4。以下是通义千问在MMLU、C-Eval、GSM8K、HumanEval、MATH等10个主流…

基于Springboot共享充电宝管理系统JAVA|VUE|SSM计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿 部署教程代码讲解代码时间修改教程 一、开发工具、运行环境、开发技术 开发工具 1、操作系统&#xff1a;Window操作系统 2、开发工具&#xff1a;IntelliJ IDEA或者Eclipse 3、数据库存储&#xff1a…