Redis存储③Redis基本命令+内部编号和架构
目录
1. Redis 命令行客户端
1.1 与 Redis 服务器交互
1.2 set 和 get 命令
2. 基本全局命令
2.1 keys
2.2 exists
2.3 del
2.4 expire
2.5 ttl
2.6 type
3. 数据结构和内部编码
4. 单线程架构
本篇完。
1. Redis 命令行客户端
1.1 与 Redis 服务器交互
根据上篇博客已经安装并启动了 Redis 服务,下面将介绍如何使用 redis-cli 连接、操作 Redis 服务。客户端和服务端的交互过程如下图所示。(Redis命令不区分大小写)
redis-cli 可以使用以下两种方式连接 Redis 服务器:
-
交互式方式
通过 redis-cli -h { host } -p { port } 的方式连接到 Redis 服务,后续所有的操作都是通过交互式的方式实现,不需要再执行 redis-cli 了,例如:
-
命令方式
用 redis-cli -h { host } -p { port } { command } 就可以直接得到命令的返回结果。
由于我们连接的 Redis 服务位于 127.0.0.1,端口也使用的是默认的 6379 端口,所以可以省略 -h { host } -p { port }。
Redis 客户端与服务端的交互过程:
1.2 set 和 get 命令
Redis 是按照键值对的方式存储数据的。
- get:根据 key 来取 value
- set:把 key 和 value 存储进去
注意:这里的 key 和 value 本质上都是字符串。
对于上面的 key value,不需要加上引号就是代表字符串的类型(加上也是可以的,单引号或双引号都行)直接按下 Tab,可以发现:系统会为我们自动补全命令(大写,Redis 中的命令不区分大小写)。
get 命令直接输入 key,就能得到 value。如果当前的 key 不存在,会返回 nil(nil 和 null / NULL 是一个意思)。
在学习 5 种数据结构之前,了解一下 Redis 的一些全局命令、数据结构和内部编码、单线程命令处理机制是十分必要的,它们能为后面内容的学习打下一个良好的基础。
主要体现在两个方面:
- Redis 的命令有上百个,如果纯靠死记硬背比较困难,但是如果理解 Redis 的一些机制,会发现这些命令有很强的通用性。
- Redis 不是万金油,有些数据结构和命令必须在特定场景下使用,一旦使用不当可能对 Redis 本身或者应用本身造成致命伤害。
2. 基本全局命令
Redis 有 5 种数据结构,它们都是键值对中的值,对于键来说有一些通用的命令(能够搭配任意一个数据结构来使用的命令),叫作全局命令。
2.1 keys
功能:用来查询当前服务器上匹配的 key。通过一些特殊符号(通配符)来描述 key 的模样,匹配上述模样的 key 就能被查询出来。
返回所有满足样式(pattern)的 key。支持如下统配样式:
- h?llo 匹配 hello , hallo 和 hxllo(? 匹配任意一个字符)
- h*llo 匹配 hllo 和 heeeello(* 匹配 0 个或者多个任意字符)
- h[ae]llo 匹配 hello 和 hallo 但不匹配 hillo(只能匹配到a、e,其它的不行,相当于给出固定选项)
- h[^e]llo 匹配 hallo , hbllo , ... 但不匹配 hello(排除 e,只有 e 匹配不了,其它的都能匹配)
- h[a-b]llo 匹配 hallo 和 hbllo(匹配 a~b 这个范围内的字符,包含两侧边界)
语法:
keys pattern
pattern 表示包含特殊符号的字符串。
命令有效版本:1.0.0 之后
时间复杂度:O(N)
需要把 Redis 里的所有 key 都遍历一遍,依次去看每一个 key 是否符合 pattern,符合就留下,不符合就跳过。
在生产环境上,一般都会禁止使用 keys 命令,尤其是 keys *(生产环境上的 key 可能非常多,而 Redis 是一个单线程的服务器,那么执行 keys * 的时间非常长,就会使 Redis 服务器被阻塞了,而无法给其他客户端提供服务)。
返回值:匹配 pattern 的所有 key。
示例:
2.2 exists
功能:判断某个 key 是否存在(也可以一次判断多个)。
Redis 支持很多数据结构,指的是一个 value 可以是一些复杂的数据结构。Redis 自身的这些键值对是通过哈希表的方式来组织的。Redis 具体的某个值又可以是一些数据结构。
语法:
exists key [key ...]
命令有效版本:1.0.0 之后.
时间复杂度:O(1)
Redis 组织这些 key 是按照哈希表的方式组织的,哈希表查询的复杂度就是 O(1),严谨来说,应该是查询 N 个 key 就是 O(N)。
返回值:key 存在的个数。
Redis 是一个客户端服务器结构的程序,客户端和服务器之间通过网络来进行通信。
两种写法的区别:
蓝色框(一次请求和一次响应):
红色框(一次请求和一次响应 + 一次请求和一次响应,四次网络通信,也就是两个轮次):
分开的写法会产生更多轮次的网络通信(效率低、成本高,和直接操作内存比)。
2.3 del
功能:删除指定的 key。
Redis 的主要应用场景就是作为缓存。此时,Redis 里存的只是一个热点数据,全量数据是在 MySQL 数据库中的。此时,如果删除了 Redis 中的几个 key,一般来说问题不大。但是,如果把 Redis 中一大半数据甚至是全部数据全删了,那么影响就很大(Redis 本来是帮 MySQL 负重前行的,而现在 Redis 数据没了,那么大部分的请求就会直接打给 MySQL,然后就容易把 MySQL 搞挂)。所以在相比之下,如果是 MySQL 中误删了一个数据,都可能影响很大。
如果把 Redis 作为数据库,此时误删数据的影响也是很大。
如果是把 Redis 作为消息队列(mq),此时误删数据的影响就应该根据具体问题来具体分析了。
语法:del key [key ...]
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:删除掉的 key 的个数。
示例:
2.4 expire
功能:为指定的 key(key 已存在,否则设置失败)添加秒级的过期时间(Time To Live TTL)。
pexpire(毫秒级)
key 的存活时间超出这个指定值就会被自动删除。业务场景举例:手机发送验证码(60s)、外卖优惠券(7天)、基于 Redis 实现的分布式锁(给 Redis 里写一个特殊的 key value,删除就是解锁。为了避免出现不能正确解锁的情况,通常都会在加锁的时候设置过期时间)。
语法:expire key seconds
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:1 表示设置成功,0 表示设置失败。
示例:
2.5 ttl
功能:获取指定 key 的过期时间,秒级。
IP 协议报头中有一个字段:ttl,它不是用时间来衡量过期的,而是用次数。
语法:ttl key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:剩余过期时间。-1 表示没有关联过期时间,-2 表示 key 不存在。
示例:
键的过期机制:
expire 和 ttl 命令都有对应的⽀持毫秒为单位的版本:pexpire 和 pttl。
Redis 的 key 的过期策略是如何实现的呢?(一个 Redis 中可能同时存在很多 key,这些 key 中可能有很大一部分都有过期时间,那么此时 Redis 如何知道哪些 key 已经过期要被删除,哪些 key 还没过期呢?)
如果直接遍历所有的 key 显然是不行的,效率非常低。Redis 整体的策略是:
- 定期删除(每次抽取一部分进行验证过期时间,保证这个抽取检查的过程足够快)
- 惰性删除(假设这个 key 已经到过期时间了,但是暂时还没删除,key 还存在,紧接着后面又有一次访问,正好用到了这个 key,于是这次访问就会让 Redis 服务器触发删除 key 的操作,同时再返回一个 nil)
为什么这里对于定期删除的时间有明确的要求呢?
因为 Redis 是单线程的程序,它的主要任务有:处理每个命令的任务、扫描过期的 key 等等,如果扫描过期 key 消耗的时间太多,那么正常处理请求命令就被阻塞了(产生了类似于执行 keys* 这样的效果。
虽然有上面讲到的两种策略结合,但整体的结果一般,仍然可能会有很多过期的 key 被残留,没有及时删除掉。Redis 为了对上述进行补充,还提供了一系列的内存淘汰策略。
如果有多个 key 过期,也可以通过一个定时器(基于优先级队列或者时间轮都可以实现比较高效的定时器)来高效 / 节省 CPU 的前提下来处理多个 key。但 Redis 并没有采取定时器的方式来实现过期 key 删除。(猜测:基于定时器实现,就需要引入多线程,但 Redis 的早起版本就奠定了单线程的基调,如果引入多线程就打破了初衷)。
定时器:在某个时间到达之后,执行指定的任务,它是基于优先级队列 / 堆的(一般的队列是先进先出,而优先级队列则是按照指定的优先级(自定义)先出)。在 Redis 过期 key 的场景中,就可以通过 “过期时间越早,就是优先级越高”。此时定时器只需要分配一个线程,不需要遍历所有的 key,只需要让这个线程去检查队首元素,看是否过期即可。如果队首元素还没过期,那么后续元素一定没过期。另外,在扫描线程检查队首元素过期时间时,也不能检查的太频繁,此时可以根据时刻和队首元素的过期时间设置一个等待,当时间差不多到了,系统再唤醒这个线程(可以节省 CPU 的开销)。
万一在线程休眠时,来了一个新的任务呢?可以在新任务添加时,唤醒刚才的线程,重新检查一下队首元素,再根据时间差距重新调整阻塞时间即可。
基于时间轮实现的定时器(把时间划分成很多小段,具体划分的粒度看实际需求):
每个小段都挂着一个链表,每个链表都代表一个要执行的任务(相当于一个函数指针以及对应的参数)。假设需要添加一个 key,这个 key 在 300ms 之后过期。此时这个指针就会每隔固定的时间间隔(此处约定时 100ms)往后走一个,每次走到一个格子就会把这个格子上链表的任务尝试执行一下。
对于时间轮来说,每个格子是多少时间,一共有多少个格子都是需要根据实际场景来灵活调配的。
2.6 type
功能:返回 key 对应的数据类型。
此处 Redis 所有的 key 都是 string,key 对应的 value 可能会存在多种类型。
语法:type key
命令有效版本:1.0.0 之后
时间复杂度:O(1)
返回值:none,string,list,set,zset,hash,stream
Redis 作为消息队列时,使用 stream 作为返回值类型。
在 Redis 中,上述几种类型的操作方式差别很大,使用的命令都是完全不同的。
示例:
3. 数据结构和内部编码
type 命令实际返回的就是当前键的数据结构类型,它们分别是:string(字符串)、list(列表)、hash(哈希)、set(集合)、zset(有序集合),但这些只是 Redis 对外的数据结构,如下图所示:
Redis 的 5 种主要的数据类型:
Redis 底层在实现上述数据结构时,会在源码底层针对上述实现进行特定的优化(内部具体实现的数据结构(编码方式)还会有变数),来达到节省时间 / 空间的效果。
实际上 Redis 针对每种数据结构都有自己的底层内部编码实现,而且是多种实现,这样 Redis 会在合适的场景选择合适的内部编码,如下表所示:
Redis 数据结构和内部编码:
从 Redis 3.2 开始,list 引入了新的实现方式:quicklist,它同时兼顾了 linkedlist 和 ziplist 的优点。quicklist 就是一个链表,每个元素又是一个 ziplist(空间和效率都折中兼顾到),类似于 C++ 中的 std::deque。
可以看到每种数据结构都有至少两种以上的内部编码实现,例如 list 数据结构包含了 linkedlist 和 ziplist 两种内部编码。同时有些内部编码,例如 ziplist,可以作为多种数据结构的内部实现,可以通过 object encoding 命令查询内部编码:
Redis 这样设计有两个好处:
- 可以改进内部编码,而对外的数据结构和命令没有任何影响,这样一旦开发出更优秀的内部编码,无需改动外部数据结构和命令。例如 Redis 3.2 提供了 quicklist,结合了 ziplist 和 linkedlist 两者的优势,为列表类型提供了一种更为优秀的内部编码实现,而对用户来说基本无感知。
- 多种内部编码实现可以在不同场景下发挥各自的优势,例如 ziplist 比较节省内存,但是在列表元素比较多的情况下,性能会下降,这时候 Redis 会根据配置选项将列表类型的内部实现转换为 linkedlist,整个过程用户同样无感知。
4. 单线程架构
Redis 使用了单线程架构来实现高性能的内存数据库服务。
Redis 只使用一个线程处理所有的命令请求,并不是说一个 Redis 服务器进程内部真的就只有一个线程,其实也有多个线程,但这多个线程是在处理网络 IO。
下面将先通过多个客户端命令调用的例子说明 Redis 单线程命令处理机制,接着分析 Redis 单线程模型为什么性能如此之高,最终给出为什么理解单线程模型是使用和运维 Redis 的关键。
现在开启了两个 redis-cli 客户端同时执行命令。
客户端 1 对 counter 做自增操作:
127.0.0.1:6379> incr counter
客户端 2 对 counter 做自增操作:
127.0.0.1:6379> incr counter
宏观上,2 个客户端是同时请求 Redis 服务的:
incr 就是 increase 自增,作用是把 key 的 value 进行 +1 操作。
线程安全问题:在多线程中,针对类似于这样的场景,两个线程尝试同时对同一个变量进行自增,表面上看是自增两次,实际上可能只自增了一次。
从客户端发送的命令经历:发送命令、执行命令、返回结果三个阶段,其中重点关注第 2 步。所谓的 Redis 是采用单线程模型执行命令的是指:虽然两个客户端看起来是同时要求 Redis 去执行命令的,也相当于 “并发” 的发起了上述的请求。但从微观角度来看,Redis 是串行 / 顺序执行这多个命令的,这些命令还是采用线性方式去执行的,只是原则上命令的执行顺序是不确定的,但一定不会有两条命令被同步执行,如下图(Redis 的单线程模型)所示,可以想象 Redis 内部只有一个服务窗口,多个客户端按照它们达到的先后顺序被排队在窗口前,依次接受 Redis 的服务,所以两条 incr 命令无论执行顺序,结果一定是 2,不会发生并发问题,这个就是 Redis 的单线程执行模型,保证了当前收到的这多个请求是串行执行的,所以不会发生上述类似的线程安全问题。多个请求同时到达 Redis 服务器,也是要先在队列中排队,再等待 Redis 服务器一个个的取出里面的命令再执行。
微观上,客户端发送命令的时间有先后次序的:
Redis 的单线程模型:
Redis 虽然是单线程模型,但为什么效率这么高,速度还能这么快呢?(参照物:MySQL、Oracle、Sql Server)
通常来讲,单线程处理能力要比多线程差,例如有 10000 公斤货物,每辆车的运载能力是每次 200 公斤,那么要 50 次才能完成;但是如果有 50 辆车,只要安排合理,只需要依次就可以完成任务。那么为什么 Redis 使用单线程模型会达到每秒万级别的处理能力呢?可以将其归结为三点:
- Redis 是纯内存访问,而数据库是访问硬盘。Redis 将所有数据放在内存中,内存的响应时长大约为 100ns,这是 Redis 达到每秒万级别访问的重要基础。Redis 的核心功能比数据库的核心功能更简单。(数据库对于数据的插入删除查询... 都有更复杂的功能支持,这样的功能势必要花费更多的开销。比如,针对插入删除,数据库中的各种约束都会使数据库做额外的工作)
- Redis 是单线程模型,避免了线程切换和竞态产生的消耗。Redis 的每个基本操作都是 “短平快” 的,就是简单操作一下内存数据,不是特别消耗 CPU 的操作。就算搞多个线程,提升也不大。单线程可以简化数据结构和算法的实现,让程序模型更简单;其次多线程避免了在线程竞争同一份共享数据时带来的切换和等待消耗。
- 非阻塞 IO。Redis 使用 epoll 作为 I/O 多路复用技术的实现,再加上 Redis 自身的事件处理模型将 epoll 中的连接、读写、关闭都转换为事件,不在网络 I/O 上浪费过多的时间,如下图所示。(本质上就是一个线程可以管理多个 socket。针对 TCP 来说,服务器这边每次要服务一个客户端都需要给这个客户端安排一个 socket。假设一个服务器服务多个客户端,同时就会有很多个 socket,但这些 socket 上并不是无时不刻都在传输数据。很多情况下,每个客户端和服务器之间的通信并没有那么频繁,此时这么多的 socket 大部分时间都是静默的,上面是没有数据需要传输的。也就是说,同一时刻只有少数 socket 是活跃的)。
Redis 使用 I/O 多路复用模型:
虽然单线程给 Redis 带来很多好处,但还是有一个致命的问题:对于单个命令的执行时间都是有要求的。如果某个命令执行过长,会导致其他命令全部处于等待队列中,迟迟等不到响应,造成客户端的阻塞,对于 Redis 这种高性能的服务来说是非常严重的,所以 Redis 是面向快速执行场景的数据库。
本篇完。
本专栏下一阶段将逐步讲解 Redis 五大主要数据结构的知识和应用。
相关文章:
Redis存储③Redis基本命令+内部编号和架构
目录 1. Redis 命令行客户端 1.1 与 Redis 服务器交互 1.2 set 和 get 命令 2. 基本全局命令 2.1 keys 2.2 exists 2.3 del 2.4 expire 2.5 ttl 2.6 type 3. 数据结构和内部编码 4. 单线程架构 本篇完。 1. Redis 命令行客户端 1.1 与 Redis 服务器交互 根据上篇…...
Vivado生成X1或X4位宽mcs文件并固化到flash
1.生成mcs文件 01.在vivado里的菜单栏选择"tools"工具栏 02.在"tools"里选择"生成内存配置文件" 03.配置参数 按照FPGA板上的flash型号进行选型,相关配置步骤可参考下图。 注意:Flash数据传输位宽如果需要选择X4位宽&am…...
07 区块链安全技术
概述 区块链的安全特性 区块链解决了在不可靠网络上可靠地传输信息的难题,由于不依赖与中心节点的认证和管理,因此防止了中心节点被攻击造成的数据泄露和认证失败的风险。 区块链安全防护的三大特点 共识机制代替中心认证机制数据篡改“一发动全身”…...
第84期 | GPTSecurity周报
GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区,集成了生成预训练Transformer(GPT)、人工智能生成内容(AIGC)以及大语言模型(LLM)等安全领域应用的知识。在这里,您可以找…...
柔性数组与c/c++程序中内存区域的划分
1.柔性数组 1.1柔性数组的定义 柔性数组是指在结构体中定义的,其大小在编译时未确定,而在运行时动态分配的数组。这种数组允许结构体的大小根据需要动态变化。语法如下: struct D {int a;int arry1[0]; };struct F {int a;int arry2[]; };…...
react页面定时器调用一组多个接口,如果接口请求返回令牌失效,清除定时器不再触发这一组请求
为了实现一个React页面使用定时器调用一组多个接口,并在任意一个接口请求返回令牌失效时清除定时器且不再触发这一组请求,可以遵循以下步骤: 1. 定义API调用函数:创建一个函数来处理一组API调用。每个API调用都应该检查响应状态以…...
使用 .NET Core 6.0 Web API 上传单个和多个文件
示例代码: https://download.csdn.net/download/hefeng_aspnet/90138968 介绍 我们将在 IFormFile 接口和 .NET 提供的其他接口的帮助下,逐步讨论单个和多个文件上传。 .NET 提供了一个 IFormFile 接口,代表 HTTP 请求中传输的文件。 此外…...
AJAX笔记入门篇
黑马程序员视频地址: 黑马程序员前端AJAX入门到实战全套教程https://www.bilibili.com/video/BV1MN411y7pw?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes&p2 目录 AJAX 概念和axios 使用 什么是AJAX? …...
RoHS 简介
RoHS(Restriction of Hazardous Substances Directive,限制有害物质指令)是欧盟制定的一项环保法规,旨在限制电气和电子设备中某些有害物质的使用,以减少这些产品对环境和人体健康的危害。 RoHS限制的有害物质及其限量…...
C# 中 default 使用详解
总目录 前言 在C#中,default 关键字用于表示类型默认值。它可以根据上下文推断出适用的类型,并返回该类型的默认值。随着C#版本的发展,default 的用法也变得更加丰富和灵活。本文将详细介绍 default 在不同场景下的使用方法及其最佳实践。 一…...
无人机在城市执法监管中的应用:技术革新与监管挑战
随着科技的不断进步,无人机技术在城市管理中的应用越来越广泛。无人机以其灵活性、高效性和低成本的优势,正在逐渐成为城市执法监管的得力助手。本文将探讨无人机在城市执法监管中的应用现状、技术优势以及面临的挑战。 无人机技术在城市执法监管中的应用…...
[ACTF2020 新生赛]Upload1
题目 以为是前端验证,试了一下PHP传不上去 可以创建一个1.phtml文件。对.phtml文件的解释: 是一个嵌入了PHP脚本的html页面。将以下代码写入该文件中 <script languagephp>eval($_POST[md]);</script><script languagephp>system(cat /flag);&l…...
ASP.NET代码审计 SQL注入篇(简单记录)
sql注入,全局搜索 Request QueryString ToString() select select * aspx是设计页面,而aspx.cs是类页面,也就是说设计页面用到的类信息在这个页面里面,其实就是把设计和实现分离开来。 源码 using System; using System.Collect…...
数据结构 链表2
目录 前言: 一,反转一个链表(迭代) 二,打印一个链表(递归) 三,反转一个链表(递归) 四,双向链表 总结 前言: 我们根据 [文章 链表1] 可以知道链表相比较于数组的优缺点和计算机…...
【leetcode100】二叉树的层序遍历
1、题目描述 给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]] 2、初始思路…...
MyBatis进阶
1. 动态SQL 1.1 <if>标签的使用(xml版本) 动态 SQL 是Mybatis的强⼤特性之⼀,能够完成不同条件下不同的 sql 拼接。 现在有一个需求.注册分为两种字段:必填字段和⾮必填字段,那如果在添加用户的时候有不确定的字段传⼊,程…...
迅为RK3568开发板驱动指南Linux中通用SPI设备驱动
在前面的章节中我们从0开始编写了一个mcp2515的驱动程序,而跟I2C设备类似,在Linux内核中也有着通用SPI设备驱动,在本章节将会讲解通用SPI设备驱动的使用,并讲解如何在应用程序中通过ioctl对SPI进行配置和使用。 硬件:迅…...
DDD架构实战第五讲总结:将领域模型转化为代码
云架构师系列课程之DDD架构实战第五讲总结:将领域模型转化为代码 一、引言 在前几讲中,我们讨论了领域模型的重要性及其在业务分析中的渐进获得方法。本讲将聚焦于如何将领域模型转化为代码,使得开发人员能够更轻松地实现用户的领域模型。 二、从模型到代码:领域驱动设计…...
C++----STL(list)
介绍 list的数据结果是一个带头双向链表。 使用 有了前面string、vector的基础,后续关于list使用的讲解主要提及与string和vector的不同之处。 使用文档:cplusplus.com/reference/list/list/?kwlist 迭代器问题 insert以后迭代器不失效 #include…...
软件测试 —— 性能测试(jmeter)
软件测试 —— 性能测试(jmeter) 什么是jmeter安装jmeterjmeter常用组件线程组取样器结果树 我们之前学习了接口测试工具Postman,我们今天要学习的是性能测试工具——jmeter 什么是jmeter Apache JMeter 是一个开源的性能测试工具ÿ…...
Zemax 非序列模式下的颜色检测器和颜色混合
在 Zemax 的非序列模式中,探测器用于捕获系统中射线的信息。可以使用各种类型的探测器来捕获光学系统性能的不同方面,例如矩形探测器,它存储撞击它的 NSC 源射线的能量数据。 另一种经常使用的探测器类型是 Detector Color,它是一…...
DBO优化最近邻分类预测matlab
蜣螂优化算法(Dung Beetle Optimizer,简称 DBO)作为一种新兴的群智能优化算法,于 2022 年末被提出,其灵感主要来源于蜣螂的滚球、跳舞、觅食、偷窃以及繁殖等行为。 本次使用的数据为 Excel 格式的分类数据集。该数据…...
【第二天】零基础入门刷题Python-算法篇-数据结构与算法的介绍-五种常见的排序算法(持续更新)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Python数据结构与算法的详细介绍1.Python中的常用的排序算法1.排序算法的介绍2.五种详细的排序算法代码 总结 前言 提示:这里可以添加本文要记…...
合并两个有序数组(Leetcode)
解题思路: 三个指针: $p1: 指向 nums1 中的最后一个非零元素。$p2: 指向 nums2 的最后一个元素。$p: 指向 nums1 的最后一位,用于存储合并后的元素。 从后往前填充: 比较 nums1[$p1] 和 nums2[$p2],较大的放入 nums1[…...
特殊类设计
[本节目标] 掌握常见特殊类的设计方式 1.请设计一个类,不能被拷贝 拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 C98 将拷贝构…...
2025.1.20——一、[RCTF2015]EasySQL1 二次注入|报错注入|代码审计
题目来源:buuctf [RCTF2015]EasySQL1 目录 一、打开靶机,整理信息 二、解题思路 step 1:初步思路为二次注入,在页面进行操作 step 2:尝试二次注入 step 3:已知双引号类型的字符型注入,构造…...
【esp32-uniapp】uniapp小程序篇02——引入组件库
一、引入组件库(可自行选择其他组件库) 接下来介绍colorUI、uview plus的安装,其他的安装可自行查找教程 1.colorUI weilanwl/coloruicss: 鲜亮的高饱和色彩,专注视觉的小程序组件库 下载之后解压,将\coloruicss-ma…...
基于单片机的智能小区门禁系统设计(论文+源码)
1总体架构 智能小区门禁系统以STM32单片机和WiFi技术为核心,STM32单片机作为主控单元,通过WiFi模块实现与手机APP的连接,构建整个门禁系统。系统硬件包括RFID模块、指纹识别模块、显示屏、按键以及继电器。通过RFID绑定IC卡、APP面部识别、指…...
tkinter绘制组件(44)——浮出ui控件
tkinter绘制组件(44)——浮出ui控件 引言布局函数结构ui框架对齐方向绑定已有控件出现和隐藏逻辑出现和隐藏动画完整代码函数 效果测试代码最终效果 github项目pip下载 引言 TinUI的浮出ui控件(flyout)其实是一个之间创建在UI框架…...
CDSN 2024博客之星总评选-主题文章创作,我的AI之路-起手篇
CDSN 2024博客之星总评选-主题文章创作,我的AI之路-起手篇 一. 回顾自己的机器学习之路二. 2024年的大模型学习三. 对自己的期望 一. 回顾自己的机器学习之路 自2019年起,我开始涉足机器学习领域,最初接触的是通过模型实现自动化的任务&…...
LLM基础知识
代替你的不是ai,而是会使用ai的人。而在这之上还有会打造ai的人。 1、大语言模型的大体现在哪里 LLM(Large Language Model 大语言模型)的大不仅仅是指训练数据巨大,更指参数数量巨大。 参数即模型内部的变量,…...
Linux 网络:交换芯片 EDSA 以太网帧简介
文章目录 1. 前言2. EDSA 协议以太网帧的发送和接收2.1 什么是 EDSA ?2.2 EDSA 以太网帧的发送2.3 EDSA 以太网帧的接收 3. 验证 1. 前言 限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。 2. EDS…...
【Git版本控制器--3】Git的远程操作
目录 理解分布式版本控制系统 创建远程仓库 仓库被创建后的配置信息 克隆远程仓库 https克隆仓库 ssh克隆仓库 向远程仓库推送 拉取远程仓库 忽略特殊文件 为什么要忽略特殊文件? 如何配置忽略特殊文件? 配置命令别名 标签管理 理…...
深入理解GPT底层原理--从n-gram到RNN到LSTM/GRU到Transformer/GPT的进化
从简单的RNN到复杂的LSTM/GRU,再到引入注意力机制,研究者们一直在努力解决序列建模的核心问题。每一步的进展都为下一步的突破奠定了基础,最终孕育出了革命性的Transformer架构和GPT大模型。 1. 从n-gram到循环神经网络(RNN)的诞生 1.1 N-gram 模型 在深度学习兴起之前,处理…...
【2024年华为OD机试】 (E卷,200分) - 最优资源分配芯片资源占用(JavaScriptJava PythonC/C++)
一、问题描述 题目解析 题目描述 某块业务芯片的最小容量单位为 1.25G,总容量为 M * 1.25G。芯片资源编号为 1, 2, …, M。该芯片支持 3 种不同的配置,分别为 A、B、C: 配置 A:占用容量为 1.25G(1 个单位ÿ…...
Spring Boot(6)解决ruoyi框架连续快速发送post请求时,弹出“数据正在处理,请勿重复提交”提醒的问题
一、整个前言 在基于 Ruoyi 框架进行系统开发的过程中,我们常常会遇到各种有趣且具有挑战性的问题。今天,我们就来深入探讨一个在实际开发中较为常见的问题:当连续快速发送 Post 请求时,前端会弹出 “数据正在处理,请…...
【开源免费】基于Vue和SpringBoot的常规应急物资管理系统(附论文)
本文项目编号 T 159 ,文末自助获取源码 \color{red}{T159,文末自助获取源码} T159,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...
差分进化算法 (Differential Evolution) 算法详解及案例分析
差分进化算法 (Differential Evolution) 算法详解及案例分析 目录 差分进化算法 (Differential Evolution) 算法详解及案例分析1. 引言2. 差分进化算法 (DE) 算法原理2.1 基本概念2.2 算法步骤3. 差分进化算法的优势与局限性3.1 优势3.2 局限性4. 案例分析4.1 案例1: 单目标优化…...
优选算法——哈希表
目录 1. 哈希表简介 2. 两数之和 3. 判定是否为字符重排 4. 存在重复元素 5. 字母异位词分组 1. 哈希表简介 2. 两数之和 题目链接:1. 两数之和 - 力扣(LeetCode) 题目展示: 题目分析: 大家来看上面的图&…...
【前端SEO】使用Vue.js + Nuxt 框架构建服务端渲染 (SSR) 应用满足SEO需求
Nuxt.js 是一个基于 Vue.js 的通用应用框架,它简化了使用 Vue 构建服务端渲染 (SSR) 应用的流程。除了 SSR 之外,Nuxt.js 还支持静态站点生成(Static Site Generation, SSG),渐进式网络应用(Progressive We…...
AI学习指南Ollama篇-Ollama简介
一、定义 大语言模型(LLM)是一种基于深度学习的自然语言处理模型,能够生成文本、回答问题、翻译语言、撰写代码等。这些模型通过海量的文本数据进行训练,学习语言的模式和结构,从而能够生成自然流畅的文本内容。随着技术的不断进步,大语言模型在各个领域都展现出了巨大的…...
Python从0到100(八十五):神经网络与迁移学习在猫狗分类中的应用
在人工智能的浩瀚宇宙中,深度学习犹如一颗璀璨的星辰,引领着机器学习和计算机视觉领域的前沿探索。而神经网络,作为深度学习的核心架构,更是以其强大的数据建模能力,成为解决复杂问题的重要工具。今天,我们…...
《最优化理论基础》8课时层次化教案
《最优化理论基础》8课时层次化教案 课程总目标 掌握最优化核心理论(最优性条件、凸分析、对偶理论);能独立实现经典优化算法(梯度法、牛顿法、约束优化建模);理解优化理论与机器学习模型的关联ÿ…...
从源码深入理解One-API框架:适配器模式实现LLM接口对接
1. 概述 one-api 是一个开源的 API 框架,基于go语言开发,旨在提供统一的接口调用封装,支持多种 AI 服务平台的集成。通过 Gin 和 GORM 等框架,框架简化了多种 API 服务的调用流程。通过适配器模式实现了与多种 大模型API 服务的集…...
2025年国产化推进.NET跨平台应用框架推荐
2025年国产化推进.NET跨平台应用框架推荐 1. .NET MAUI NET MAUI是一个开源、免费(MIT License)的跨平台框架(支持Android、iOS、macOS 和 Windows多平台运行),是 Xamarin.Forms 的进化版,从移动场景扩展到…...
Tensor 基本操作4 理解 indexing,加减乘除和 broadcasting 运算 | PyTorch 深度学习实战
前一篇文章,Tensor 基本操作3 理解 shape, stride, storage, view,is_contiguous 和 reshape 操作 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started Tensor 基本使用 索引 indexing示例代码 加减…...
图扑 2024 全年精彩回顾 | 稳步向前
2024 年即将过去,回顾这一年,图扑软件在多个领域取得了显著成就,我们斩获多项行业奖项,稳步提升了市场地位,并在产品创新上推出了一系列新功能,提升了用户体验。与此同时,通过与合作伙伴紧密协作…...
[Python学习日记-79] socket 开发中的粘包现象(解决模拟 SSH 远程执行命令代码中的粘包问题)
[Python学习日记-79] socket 开发中的粘包现象(解决模拟 SSH 远程执行命令代码中的粘包问题) 简介 粘包问题底层原理分析 粘包问题的解决 简介 在Python学习日记-78我们留下了两个问题,一个是服务器端 send() 中使用加号的问题,…...
【数据结构】深入解析:构建父子节点树形数据结构并返回前端
树形数据结构列表 一、前言二、测试数据生成三、树形代码3.1、获取根节点3.2、遍历根节点,递归获取所有子节点3.3、排序3.4、完整代码 一、前言 返回前端VO对象中,有列情况列表展示需要带树形结构,例如基于RBAC权限模型中的菜单返回…...
【统计的思想】假设检验(二)
假设检验是根据人为设定的显著水平,对被测对象的总体质量特性进行统计推断的方法。 如果我们通过假设检验否定了零假设,只是说明在设定的显著水平下,零假设成立的概率比较小,并不是说零假设就肯定不成立。如果零假设事实上是成立…...