Redis常用数据结构及原理

Redis支持字符串、哈希、列表、集合、有序集合和位图等多种数据类型。字符串的底层数据结构是SDS,提供高效修改操作;哈希和集合使用哈希表,实现快速查找和插入;列表基于双向链表,适合队列和栈操作;有序集合结合跳跃表和哈希表,实现有序数据存储;位图利用字符串存储位,适用于统计和记录场景。

Redis常用六种数据类型

Redis 支持多种数据类型,每种类型都具有不同的特性和用途。以下是 Redis 中常见的数据类型:

一、字符串(String)

1、基本介绍

字符串是最基本的数据类型,可以存储任意类型的数据,如文本、数字或序列化对象。可以使用字符串相关的命令对其进行操作,如设置值(SET)、获取值(GET)、增加数值(INCR)、追加字符串(APPEND)等。

2、底层数据结构和原理

在 Redis 中,字符串类型的底层数据结构和原理是简单动态字符串(SDS,Simple Dynamic String)。

简单动态字符串是 Redis 自己实现的一种字符串结构,相比于传统的 C 字符串(以空字符 ‘\0’ 结尾的字符数组),简单动态字符串具有以下优势:

  • O(1) 时间复杂度的修改操作:简单动态字符串通过维护字符串长度和可用空间的变量,可以在 O(1) 时间复杂度内进行字符串的修改操作,而不需要像传统 C 字符串那样进行内存拷贝和分配。

  • 动态扩容和缩容:简单动态字符串在需要扩容时,可以按需动态地增加内存空间,而不是事先分配固定大小的缓冲区。这种动态扩容的机制使得字符串的长度可以根据需要进行自由调整,节省了内存空间。

  • 二进制安全:简单动态字符串可以存储任意二进制数据,不仅仅限于文本字符串。这使得 Redis 可以在字符串类型中存储和处理二进制数据,而不会受到 C 字符串的限制。

  • 内存预分配和惰性空间释放:简单动态字符串在进行扩容时,会预先分配一定的额外空间,以减少频繁的内存分配操作。同时,在字符串缩短时,不会立即释放多余的空间,而是保留一部分空间,以备后续使用,从而提高了性能。

总之,简单动态字符串是 Redis 中字符串类型的底层数据结构,通过动态扩容和缩容、O(1) 时间复杂度的修改操作等特性,提供了高效的字符串操作。这种数据结构使得 Redis 的字符串类型非常适用于存储和处理各种类型的数据,包括文本和二进制数据。

这个其实和Java中的ArrayList的实现比较像,ArrayList使用的是动态数组。如果读者比较感兴趣的话,后续我可以单独写一篇文章来着重讲述两者的区别。

二、哈希(Hash)

1、基本介绍

哈希是一种键值对集合,类似于对象或字典。每个哈希可以存储多个字段和对应的值。可以使用哈希相关的命令对其进行操作,如设置**字段值(HSET)、获取字段值(HGET)、获取全部字段和值(HGETALL)**等。

2、底层数据结构和原理

在 Redis 中,Hash(哈希)的底层数据结构是哈希表(Hash Table)。

哈希表是一种基于键值对的数据结构,通过哈希函数将键映射到存储位置,实现了高效的键值查找和插入操作。在 Redis 的哈希中,哈希表被用来存储哈希的键值对。

Hash大家应该都比较熟悉了,这里简单讲一下Redis 中哈希底层数据结构和原理的一些关键点:

  • 哈希表优势:使用哈希表作为哈希的底层数据结构有几个优势。首先,通过哈希表,可以以常数时间复杂度 O(1) 来执行插入、删除和查找操作。其次,哈希表可以高效地处理大量的键值对数据,具有良好的扩展性。

  • 哈希表存储键值对:在 Redis 中,每对哈希的键值对被存储为哈希表的键值对。哈希表的键被称为字段(field),而哈希表的值被称为值(value)。通过哈希表的键,可以快速检索和操作哈希中的键值对。

  • 哈希表的键冲突处理:由于哈希函数的输出空间有限,不同的键可能映射到相同的哈希表位置,这就是所谓的键冲突。为了解决键冲突,Redis 使用链地址法(Separate Chaining)来处理相同哈希值的键。具体来说,Redis 将具有相同哈希值的键值对放在同一个链表中,通过链表来存储冲突的键值对。

  • 哈希表的扩容和缩容:为了保持哈希表的高效性能,Redis 在哈希表达到一定负载因子时会自动进行扩容操作。扩容操作涉及重新计算哈希函数和重新分配空间,以便保持较低的键冲突率。同样,当哈希表的使用率较低时,Redis 会自动进行缩容操作,以节省内存空间。

  • 哈希的常用操作:Redis 提供了一系列命令来操作哈希,如添加字段和值(HSET)、获取值(HGET)、删除字段(HDEL)等。这些命令通过操作底层的哈希表来实现哈希的操作。

Redis 中的哈希数据类型通过使用哈希表作为底层数据结构,实现了高效的键值查找和插入操作。这种数据结构使得 Redis 的哈希非常适用于存储和操作具有键值对结构的数据,如用户信息、配置信息等。

三、列表(List)

1、基本介绍

列表是一个有序的字符串元素集合,可以在列表的两端进行插入或删除操作。列表可以用作队列或栈。您可以使用列表相关的命令对其进行操作,如插入元素到列表头(LPUSH)、弹出列表尾部元素(RPOP)、获取指定范围的元素(LRANGE)等。

2、底层数据结构和原理

在 Redis 中,List(列表)的底层数据结构是双向链表(doubly linked list)。(注:Java中的LinkedList底层也是双向链表,可以对比学习。)

双向链表是一种由多个节点组成的数据结构,每个节点包含一个值和两个指针,分别指向前一个节点和后一个节点。在 Redis 中,每个列表都由一个双向链表来实现,列表的每个元素都存储在一个节点中。

Redis 通过使用双向链表作为列表的底层数据结构,实现了对列表的高效操作。以下是一些关于 Redis 列表底层数据结构和原理的重要细节:

  • 双向链表优势:使用双向链表作为列表的底层数据结构有几个优势。首先,它允许在列表的两端进行高效的插入和删除操作,时间复杂度为 O(1)。其次,双向链表可以按照顺序遍历和反向遍历列表,使得在有序列表中执行范围操作非常高效。

  • 列表的头节点和尾节点:Redis 中的列表有一个特殊的头节点和尾节点,分别表示列表的开头和结尾。这些节点不包含实际的值,只是作为指示列表边界的标记。它们的存在使得在列表两端执行插入和删除操作更加高效。

  • 列表的节点结构:每个列表节点包含三个主要部分。第一个部分是前置节点指针,指向前一个节点;第二个部分是后置节点指针,指向后一个节点;第三个部分是值,存储实际的列表元素。

  • 列表的头指针和尾指针:Redis 中的列表有两个指针,分别指向列表的头节点和尾节点。这些指针使得在列表两端执行插入、删除和访问操作更加方便和高效。

  • 列表的常用操作:Redis 提供了一系列命令来操作列表,如插入元素到列表头部(LPUSH)、插入元素到列表尾部(RPUSH)、从列表头部弹出元素(LPOP)、从列表尾部弹出元素(RPOP)等。这些命令通过操作双向链表的节点来实现列表的操作。

Redis 中的列表数据类型通过使用双向链表作为底层数据结构,实现了高效的插入、删除和访问操作。这种数据结构使得 Redis 列表非常适用于队列、栈、任务列表等应用场景,同时提供了丰富的命令和操作来满足不同的需求。

四、集合(Set)

1、基本介绍

集合是一组唯一的、无序的字符串元素集合。集合支持添加、删除和判断元素是否存在的操作。您可以使用集合相关的命令对其进行操作,如添加元素到集合(SADD)、删除元素(SREM)、判断元素是否存在(SISMEMBER)等。

2、底层数据结构和原理

在 Redis 中,Set(集合)的底层数据结构是哈希表(Hash Table)。

哈希表是一种基于键值对的数据结构,它通过哈希函数将键映射到存储位置,从而实现高效的键值查找和插入操作。在 Redis 的集合中,哈希表被用来存储集合的元素。

以下是 Redis 中集合底层数据结构和原理的一些关键点:

  • 哈希表优势:使用哈希表作为集合的底层数据结构有几个优势。首先,通过哈希表,可以以常数时间复杂度 O(1) 来执行插入、删除和查找操作。其次,哈希表可以高效地处理大量的键值对数据,具有良好的扩展性。

  • 哈希表存储集合元素:在 Redis 中,每个集合元素被存储为哈希表的键,而哈希表的值则被设置为一个固定的空占位符。通过哈希表的键,可以快速检索和操作集合中的元素。

  • 哈希表的键冲突处理:由于哈希函数的输出空间有限,不同的键可能映射到相同的哈希表位置,这就是所谓的键冲突。为了解决键冲突,Redis 使用链地址法(Separate Chaining)来处理相同哈希值的键。具体来说,Redis 将具有相同哈希值的键放在同一个链表中,通过链表来存储冲突的键值对。

  • 哈希表的扩容和缩容:为了保持哈希表的高效性能,Redis 在哈希表达到一定负载因子时会自动进行扩容操作。扩容操作涉及重新计算哈希函数和重新分配空间,以便保持较低的键冲突率。同样,当哈希表的使用率较低时,Redis 会自动进行缩容操作,以节省内存空间。

  • 集合的常用操作:Redis 提供了一系列命令来操作集合,如添加元素到集合(SADD)、从集合中移除元素(SREM)、判断元素是否存在于集合中(SISMEMBER)等。这些命令通过操作底层的哈希表来实现集合的操作。

Redis 中的集合数据类型通过使用哈希表作为底层数据结构,实现了高效的插入、删除和查找操作。这种数据结构使得 Redis 集合非常适用于存储和操作唯一值的场景,并提供了丰富的命令和操作来满足不同需求。

五、有序集合(Sorted Set)

1、基本介绍

有序集合是一种在集合基础上增加了一个分数(score)的数据结构。每个元素都有一个唯一的值和一个对应的分数,通过分数可以对元素进行排序。您可以使用有序集合相关的命令对其进行操作,如添加元素到有序集合(ZADD)、根据分数范围获取元素(ZRANGEBYSCORE)、获取指定排名范围的元素(ZRANGE)等。

2、底层数据结构和原理

在 Redis 中,Sorted Set(有序集合)的底层数据结构是跳跃表(Skip List)和哈希表(Hash Table)的结合使用。

跳跃表是一种有序数据结构,类似于链表,但在每个节点中添加了多个指向其他节点的指针,从而实现高效的查找和范围操作。哈希表用于存储每个成员及其对应的分数。

以下是 Redis 中有序集合底层数据结构和原理的一些关键点:

  • 跳跃表:有序集合使用跳跃表作为有序数据的主要存储结构。跳跃表中的每个节点都包含一个成员和一个分数,节点按照成员的字典序进行排序。通过多个层级的指针,跳跃表可以快速跳过一些节点,从而加快查找速度。

  • 跳跃表的层级:跳跃表由多个层级组成,每个层级都是一个有序链表。最底层是包含所有成员的完整链表,而上层则是通过“跳跃”的方式连接较少的节点。这种层级结构使得在跳跃表中查找成员的时间复杂度为 O(log n)。

  • 哈希表:除了跳跃表,Redis 还使用哈希表来存储每个成员及其对应的分数。哈希表通过将成员作为键、分数作为值来存储数据。这样,当需要根据成员进行查找或更新时,可以通过哈希表快速定位到对应的节点。

  • 跳跃表和哈希表的结合使用:通过将跳跃表和哈希表结合使用,Redis 实现了有序集合数据类型的高效操作。跳跃表提供了快速的有序查找和范围操作,而哈希表则提供了快速定位成员的能力。

  • 有序集合的常用操作:Redis 提供了一系列命令来操作有序集合,如添加成员和分数(ZADD)、根据分数范围获取成员(ZRANGEBYSCORE)、获取成员的排名(ZRANK)等。这些命令通过操作底层的跳跃表和哈希表来实现有序集合的操作。

Redis 中的有序集合数据类型通过使用跳跃表和哈希表的结合,实现了高效的有序集合操作。跳跃表提供了快速的查找和范围操作,而哈希表提供了快速定位成员的能力。这种数据结构使得 Redis 有序集合非常适用于实现排行榜、计数器和范围查询等应用场景。

六、Bitmaps

1、基本介绍

位图是一种使用二进制位来存储和操作数据的数据结构。您可以使用位图相关的命令对其进行操作,如设置位(SETBIT)、获取位(GETBIT)、对多个位进行逻辑操作(BITOP)等。

除了以上常见的数据类型,Redis 还支持其他数据类型,如地理位置(Geospatial)、流(Stream)等。每种数据类型都有各自的用途和适用场景,您可以根据具体的需求选择合适的数据类型来存储和操作数据。

2、底层数据结构和原理

在 Redis 中,Bitmaps(位图)的底层数据结构是字符串(String)。

字符串是 Redis 中最基本的数据结构,可以存储二进制数据。在 Bitmaps 中,每个位(bit)都被存储为字符串中的一个字符,可以表示为 0 或 1。Redis 使用字符串来表示位图,并提供了一系列命令来操作位图数据。

以下是 Redis 中位图底层数据结构和原理的一些关键点:

  • 字符串存储位:在 Redis 中,每个位都由一个字符来表示。位图使用 0 或 1 来表示位的状态,通常使用字符 “0” 和 “1” 分别表示位值为 0 或 1。

  • 字符串的位操作:Redis 提供了一些位操作命令,如设置位(SETBIT)、获取位(GETBIT)、对多个位进行逻辑操作(BITOP)等。这些命令通过操作字符串的位来实现位图的操作。

  • 字符串的二进制存储:Redis 使用字节序列来存储字符串,每个字节可以表示 8 个位。位图中的每个位会转换成对应字节中的某一位。

  • 位图的大小:Redis 中的位图可以非常大,可以有 2^32 = 4294967296 个位,即可以表示一个长度为 4294967296 的位序列。

  • 位图的应用:位图在 Redis 中广泛应用于各种场景,如统计在线用户、记录用户行为、判断某个元素是否存在等。由于位图的存储非常紧凑,可以有效地节省存储空间。

请注意,位图虽然非常高效,但它是以整个字符串作为单位进行操作的,如果只需要操作其中的某些位,可能会涉及到整个字符串的读取和写入,可能会对性能产生影响。因此,在使用位图时,需要根据实际需求和数据规模进行权衡和设计。

除了以上常见的数据类型,Redis 还支持其他数据类型,如地理位置(Geospatial)、流(Stream)等。每种数据类型都有各自的用途和适用场景,可以根据具体的需求选择合适的数据类型来存储和操作数据。

欢迎关注我的公众号,除了分享一些技术文章,还会分享一些工作经验和有趣的事。
请添加图片描述

基于分布式模型预测控制的多个固定翼无人机一致性控制(Matlab代码实现)内容概要:本文围绕“基于分布式模型预测控制的多个固定翼无人机一致性控制”展开,采用Matlab代码实现相关算法,属于顶级EI期刊的复现研究成果。文中重点研究了分布式模型预测控制(DMPC)在多无人机系统中的一致性控制问题,通过构建固定翼无人机的动力学模型,结合分布式协同控制策略,实现多无人机在复杂环境下的轨迹一致性和稳定协同飞行。研究涵盖了控制算法设计、系统建模、优化求解及仿真验证全过程,并提供了完整的Matlab代码支持,便于读者复现实验结果。; 适合人群:具备自动控制、无人机系统或优化算法基础,从事科研或工程应用的研究生、科研人员及自动化、航空航天领域的研发工程师;熟悉Matlab编程和基本控制理论者更佳; 使用场景及目标:①用于多无人机协同控制系统的算法研究与仿真验证;②支撑科研论文复现、毕业设计或项目开发;③掌握分布式模型预测控制在实际系统中的应用方法,提升对多智能体协同控制的理解与实践能力; 阅读建议:建议结合提供的Matlab代码逐模块分析,重点关注DMPC算法的构建流程、约束处理方式及一致性协议的设计逻辑,同时可拓展学习文中提及的路径规划、编队控制等相关技术,以深化对无人机集群控制的整体认知。
<think>我们正在处理一个关于AT命令调用大模型API时遇到的错误问题。用户在使用AT命令`HTTPDATAEX`调用豆包doubao)模型API时出现了错误。我们需要逐步分析可能的原因和解决方案。首先,我们需要了解AT命令`HTTPDATAEX`的用途。在通信模组中,AT命令通常用于控制调制解调器或通信模块。`HTTPDATAEX`命令很可能是用于发送HTTP请求的数据(可能是POST请求的数据部分)。因此,错误可能出现在发送的数据格式、长度或内容上。 常见的错误原因可能包括: 1. **数据长度错误**:`HTTPDATAEX`命令可能需要指定数据的长度,如果实际发送的数据长度与指定长度不符,会导致错误。2.**数据格式错误**:发送的数据可能不符合API要求的格式(例如,JSON格式不正确)。3.**URL或参数错误**:虽然`HTTPDATAEX`主要用于发送数据,但前提是已经通过其他AT命令(如`HTTPPARA`)设置了正确的URL和请求头。4.**网络连接问题**:可能网络连接尚未建立或已断开。 5. **API鉴权问题**:调用豆包模型API可能需要API密钥或其他鉴权信息,这些信息可能未正确设置。接下来,我们按照典型步骤来设置HTTP请求并发送数据:###步骤1:设置HTTP参数(URL、请求头等) 通常,使用AT命令设置HTTP参数,例如:```AT+HTTPPARA="URL","https://api.doubao.com/chat/completions"AT+HTTPPARA="USERDATA","Content-Type:application/json\r\nAuthorization:Bearer<your_api_key>"```###步骤2:设置HTTP数据使用`HTTPDATAEX`命令发送数据。该命令的格式可能如下: ```AT+HTTPDATAEX=<size>,<timeout> ```然后,模组会返回一个提示(如`DOWNLOAD`),接着发送实际数据(注意:数据长度必须与`<size>`一致)。###步骤3:执行HTTP请求使用`HTTPACTION`命令执行请求(例如,`AT+HTTPACTION=1`表示POST请求)。###错误分析如果`HTTPDATAEX`命令报错,可能是:-数据长度`<size>`设置不正确(大于或小于实际数据长度)。 -数据内容不符合要求(比如不是有效的JSON)。-在发送数据之前,没有正确设置URL或请求头。 ###解决方案1. **检查数据长度**:确保`<size>`参数等于实际发送数据的字节数(包括换行符等)。例如,如果数据是JSON字符串,可以使用工具计算其长度(注意:中文字符在UTF-8中通常占3个字节)。 2. **检查数据格式**:豆包模型API通常要求JSON格式的请求体。例如:```json{"model":"your_model","messages":[{"role":"user", "content":"你好"}]}```确保JSON是有效的,并且正确转义了特殊字符。3.**检查鉴权信息**:在请求头中设置正确的`Authorization`(通常为`Bearer <your_api_key>`)。4.**检查超时时间**:`<timeout>`参数应足够大(例如10000毫秒),以便模组有足够时间接收数据。 5. **检查网络连接**:确保模组已成功附着网络并建立了GPRS/PPP连接。###示例调用流程假设我们要发送以下JSON数据(长度为70字节,注意:实际长度需要精确计算): ```json{"model":"your_model","messages":[{"role":"user","content":"你好"}]} ```AT命令序列可能如下:``` AT+HTTPINITAT+HTTPPARA="URL","https://api.doubao.com/chat/completions" AT+HTTPPARA="USERDATA","Content-Type: application/json\r\nAuthorization: Bearer sk-xxx" AT+HTTPDATAEX=70,10000<等待模组返回"DOWNLOAD"或类似提示>{"model":"your_model","messages":[{"role":"user","content":"你好"}]}AT+HTTPACTION=1AT+HTTPREADAT+HTTPTERM``` ###注意事项-不同模组的AT命令可能略有差异,请参考具体模组的手册。 -确保在发送数据时,模组处于正确状态(例如,已经初始化HTTP服务并设置了URL)。-如果数据中包含中文字符,确保整个通信过程使用UTF-8编码(可能需要通过`HTTPPARA`设置`Content-Type`为`application/json;charset=UTF-8`)。§§相关问题§§1.如何精确计算JSON数据的字节长度? 2.使用AT命令调用HTTPAPI时,常见的错误码有哪些?3.豆包模型API的具体参数要求是什么? 4.如何通过AT命令设置HTTPS?5.如何调试AT命令的通信过程?</think>### AT命令调用豆包模型API时HTTPDATAEX错误分析 该错误通常发生在使用蜂窝模组(如SIMCOM、Quectel系列)的AT命令发送HTTP POST数据时,具体涉及`AT+HTTPDATAEX`或`AT+HTTPDATA`命令。以下是常见原因和解决方案: --- #### 1. **数据长度不匹配** [^1] - **问题**:`HTTPDATAEX`要求先指定数据长度(如`AT+HTTPDATAEX=1024,10000`),但实际发送的数据字节数与声明值不一致 - **解决**: - 精确计算JSON请求体的字节数(含空格/换行符) - 使用Python验证: ```python import json request = {"model": "skylark-pro", "messages": [{"role": "user", "content": "你好"}]} byte_len = len(json.dumps(request).encode('utf-8')) print(f"AT+HTTPDATAEX={byte_len},30000") # 输出精确长度 ``` --- #### 2. **JSON格式错误** [^2] - **典型错误**: - 未转义双引号:`{"prompt": "Say "hello""}` - 缺少逗号或括号 - **验证工具**: ```bash curl -X POST https://api.doubao.com/chat \ -H "Content-Type: application/json" \ -d '{"model":"skylark-lite","messages":[{"role":"user","content":"你好"}]}' ``` 先用curl测试JSON有效性 --- #### 3. **模组固件限制** - **常见问题**: - 旧版SIM800系列最大数据长度限制为1024字节 - 豆包API响应可能超过模组缓冲区 - **解决方案**: ```at AT+HTTPPARA="REDIR",1 // 启用重定向 AT+HTTPPARA="BREAK",1 // 启用分块传输 AT+HTTPDATAEX=512,30000 // 减小单次数据块 ``` --- #### 4. **HTTP头部缺失** - **必要头部**: ```at AT+HTTPPARA="USERDATA","Content-Type: application/json\r\nAuthorization: Bearer YOUR_API_KEY" ``` - **验证步骤**: 1. 检查`USERDATA`中的`\r\n`是否完整 2. 确认API密钥未过期 --- #### 5. **超时设置不足** 豆包API响应时间可能较长: ```at AT+HTTPDATAEX=1200,60000 // 超时设为60秒 AT+HTTPACTION=1 // 执行POST AT+HTTPREAD=120000 // 读取响应超时120秒 ``` --- #### 6. **HTTPS证书问题** 若使用自签名证书: ```at AT+HTTPSSL=1 AT+HTTPPARA="IGNORE_SSL",1 // 跳过证书验证(测试环境) ``` > **调试建议**:先用`AT+HTTPDEBUG=2`启用调试模式,通过串口日志检查实际发送的数据包[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大骨熬汤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值