聊聊 Redis 的一些有趣的特性(上)

news2025/3/16 16:33:00

聊聊 Redis 的一些有趣的特性(上)

一、持久化

Redis 是内存数据库,数据全部保存在内存中。如果服务器发生宕机,内存中的数据将会全部丢失。为防止系统崩溃后数据丢失,Redis 提供了持久化功能,可将内存中的数据保存到磁盘。

Redis 对持久化的需求

  • 作为缓存时 :系统更注重性能,缓存数据如果丢失,可以从数据库中重新查询获取,因此对 Redis 持久化的要求并不高,可以容忍短时间的数据丢失。
  • 作为数据库时 :数据量大,且对数据完整性和一致性要求较高,此时 Redis 持久化就显得尤为重要,需要确保数据不丢失或尽可能减少数据丢失。

Redis 提供的两种持久化方式

  • RDB 持久化 :基于快照的持久化方式,将内存中的数据以快照的形式写入磁盘。适用于数据完整性和一致性要求不高的场景。
  • AOF 持久化 :基于日志的持久化方式,将内存中的数据以日志的形式写入磁盘。适用于数据完整性和一致性要求较高的场景。

我们可以选择开启其中一种持久化方式,也可以选择不开启(如果对数据完整性和一致性要求不高,可以关闭持久化)。

AOF 持久化相较于 RDB 更加可靠而完整,但会带来更大的磁盘占用和性能开销,属于更高级别的持久化,当同时开启两种持久化机制时 Redis 会优先使用 AOF 持久化,当 AOF 持久化文件过大时会自动切换到 RDB 持久化。

(一) RDB 持久化

RDB 是 Redis 默认的持久化方式,它将 Redis 内存中的数据以快照的方式写入磁盘。

  • 特点 :RDB 是基于快照的持久化方式,持久化的是某一个时间点的 Redis 内存全量数据,并不是实时的,会造成一定程度的数据丢失。例如,假如每隔一个小时进行一次快照持久化,当 Redis 在 10:00 进行过一次快照持久化时,从 10:00 到 11:00 这一小时内 Redis 发生的任何修改都不会被持久化到磁盘,从而造成部分数据的丢失。
  • 优点 :RDB 是基于全量数据进行的持久化,数据文件非常紧凑,适合用于数据备份和灾难恢复。恢复时,可以直接加载数据文件到 Redis 内存中。
  • 实现机制 :进行 RDB 持久化时,Redis 会 fork 一个子进程,由子进程负责执行 IO 操作,将内存中的数据写入到临时文件中,待持久化过程结束后,再替换之前的快照文件;主进程继续处理命令请求,不会受到影响。

RDB 持久化的性能优化

  • copy-on-write 策略 :从主进程 fork 子进程时采用 copy-on-write 策略,父进程和子进程共享同一份数据,只有在修改数据时,父进程才会复制需要变化的那部分数据。这样可以大大减少 fork 子进程的时间和内存空间占用,提高 Redis 性能。

(二) AOF 持久化

AOF 持久化是 Redis 另一种持久化方式,它将 Redis 内存中的数据以日志的方式写入磁盘。

  • 特点 :AOF 会记录每一笔针对 Redis 数据库的写入操作,并将这些命令以日志的形式保存到磁盘。当 Redis 重启时,会从日志中重新执行写命令,从而达到恢复数据的目的。AOF 弥补了 RDB 持久化的不足,能够做到实时持久化,实现更可靠更耐久的数据持久化。
  • 实现机制 :基于日志的持久化方式是一种追加的方式,不会进行随机写入磁盘寻址操作,而是将每一个写命令都追加到日志末尾,是一种顺序写的机制,尽管针对磁盘的读写操作效率总是比较低,但是相较于随机的写入方式还是能一定程度上提高写操作的效率。

AOF 持久化的性能与策略

  • 刷盘策略配置 :事实上,AOF 为数据操作记录日志时,也不会立即将数据写入磁盘,而是先写入内存中日志文件的缓冲区。至于什么时候真正写入磁盘,实现持久化,可以进行配置。默认是每秒钟将缓冲区中的日志写入磁盘,同时提供了不主动控写入磁盘时机(由操作系统决定什么时候写入磁盘)、以及每次写的时候都强制写入磁盘的选项。
  • 综合考虑性能与数据完整性 :我们必须清楚一点,基于 AOF 的数据持久化是以性能为代价的,如果我们要求每次写入数据都进行 fsync 操作,那么每次写入数据都会导致磁盘 IO 开销,尽管这样做会保证数据不丢失,但将导致效率非常低下。正确的做法是综合衡量性能要求和数据完整性要求,选择合适的刷盘策略。

AOF 日志重写机制

  • 日志文件膨胀问题 :AOF 记录的是日志而非数据文件,日志文件体积相较于紧凑的数据文件更大;另一方面,由于 AOF 记录的是每一笔写操作,因此 AOF 日志文件中会包含大量远古的无用的命令,例如对已经过期的键的操作,和重复的添加删除操作,这些命令对数据完整性没有任何意义。
    例如,执行以下操作:

    redis> set a 1 es 1
    redis> set b 2 es 2
    redis> set c 3 es 3
    redis> set d 4
    redis> del d
    redis> set d 4
    redis> del d
    redis> set d 4
    redis> del d
    redis> set d 4
    

    这个例子中,我们执行了若干条操作,并通过 es 选项设置了过期时间,这些操作都会被记录到日志文件当中,然而,最后 redis 中的数据只有 d -> 4 这一个键值对,因此除了最后一条命令,其余的命令对数据完整性都没有任何意义。

    长此以往,日志文件的体积会越来越大,最后,内存中的数据可能很少,而日志文件却记录了若干年积累下来的命令。这时一旦发生宕机,重启时 redis 将从几年前的第一条数据开始恢复,我们无法想象恢复数据需要多少时间。

  • 重写机制实现 :AOF 持久化机制提供了重写的机制。重写操作也会 fork 一个子进程,将内存中的数据翻译成最小命令,并以日志的形式写入到临时文件中,待持久化过程结束后,再将原来的日志文件替换为临时文件。整个过程是增量的,不会影响到现有的数据,因此绝对安全。上面的例子中,重写时 Redis 会将 d -> 4 这一个键值对翻译成 set d 4 命令,并写入到临时文件中,替换之前的日志文件,从而减少日志文件体积,提高恢复数据的效率。

(三) RDB 和 AOF 的配合使用

Redis 4.0 版本引入了 RDB 和 AOF 持久化的配合使用,即可以同时开启 RDB 和 AOF 持久化。

在这种情况下,重写 AOF 文件就不需要将数据集翻译成指令,而是直接基于 RDB 进行增量记录,结合了两种持久化方式的优势,既提高了数据持久化的效率,又保证了数据的完整性。

缓存的设计模式

Redis 缓存的设计模式包括:

  1. Write-Through 直写缓存模式。
  2. Write-Behind 后写缓存模式。
  3. Cache-Aside 旁路缓存模式。
  4. Delay-Double-Delete 延迟双删缓存模式。

在这里插入图片描述

(一) Write-Through 直写缓存模式

直写缓存模式是指读写数据时 发生 读穿透 Read-Through 和 写穿透 Write-Through

  • Read-Through 和 Write-Through 是两种与缓存相关的策略,它们主要用于缓存系统与持久化存储之间的数据交互,旨在确保缓存与底层数据存储的一致性。

Read-Through 是一种在缓存中找不到数据时,自动从持久化存储中加载数据并回填到缓存中的策略。具体执行流程如下:

  • 客户端发起读请求到缓存系统。
  • 缓存系统检查是否存在请求的数据。
  • 如果数据不在缓存中,缓存系统会透明地向底层数据存储(如数据库)发起读请求。
  • 数据库返回数据后,缓存系统将数据存储到缓存中,并将数据返回给客户端。
  • 下次同样的读请求就可以直接从缓存中获取数据,提高了读取效率。

在这里插入图片描述

  • 在缓存未命中的情况下,Read-Through 策略会自动隐式地从数据库加载数据并填充到缓存中,而无需应用程序显式地进行数据库查询。
  • 缓存系统承担了更多的职责,实现了更紧密的缓存与数据库集成,从而简化了应用程序的设计和实现。
  • 对于用户来说,读取数据的过程就是在和缓存系统交互,用户感受不到数据库的存在。

Write-Through 是一种在缓存中更新数据时,同时将更新操作同步到持久化存储的策略。具体流程如下:

  • 当客户端向缓存系统发出写请求时,缓存系统首先更新缓存中的数据。
  • 同时,缓存系统还会把这次更新操作同步到底层数据存储(如数据库)。
  • 当数据在数据库中成功更新后,整个写操作才算完成。
  • 这样,无论是从缓存还是直接从数据库读取,都能得到最新一致的数据。

在这里插入图片描述

Read-Through 和 Write-Through 的共同目标是确保缓存与底层数据存储之间的一致性,并通过自动化的方式隐藏了缓存与持久化存储之间的交互细节,简化了客户端的处理逻辑。

  • 这两种策略经常一起使用,以提供无缝且一致的数据访问体验,特别适用于那些对数据一致性要求较高的应用场景。
  • 这种缓存设计模式在每次写入时,不论数据是否真正活跃都会写入到缓存中,因此这种模式适用于全量数据活跃度较高的场景。
  • 由于内存中存储了全量的数据,因此直写缓存策略会带来更高的内存消耗,因此在数据量较大的情况下不建议使用。
  • 虽然它们有助于提高数据一致性,但在高并发或网络不稳定的情况下仍然需要考虑并发控制和事务处理等问题,以防止数据不一致的情况发生。

(二) Write-Behind 后写缓存模式

Write Behind(异步缓存写入),也称为 Write Back(回写)或 异步更新策略,是一种在处理缓存与持久化存储(如数据库)之间数据同步时的策略。在这种模式下,当数据在缓存中被更新时,并非立即同步更新到数据库,而是将更新操作暂存起来,随后以异步的方式批量地将缓存中的更改写入持久化存储。其流程如下:

  • 应用程序首先在缓存中执行数据更新操作,而不是直接更新数据库。
  • 缓存系统会将此次更新操作记录下来,暂存于一个队列(如日志文件或内存队列)中,而不是立刻同步到数据库。
  • 在后台有一个独立的进程或线程定期(或者当队列积累到一定大小时)从暂存队列中取出更新操作,然后批量地将这些更改写入数据库。

在这里插入图片描述

  • 使用 Write Behind 策略时,由于更新并非即时同步到数据库,所以在异步处理完成之前,如果缓存或系统出现故障,可能会丢失部分更新操作。
  • 并且,对于高度敏感且要求强一致性的数据,Write Behind 策略并不适用,因为它无法提供严格的事务性和实时一致性保证。
  • Write Behind 适用于那些可以容忍一定延迟的数据一致性场景,通过牺牲一定程度的一致性换取更高的系统性能和扩展性。

以上两种缓存设计模式都是以 缓存层 作为用户直接视图,用户只知道从缓存中读写,而不知道底层数据存储的存在,屏蔽了数据库的读写过程。

由于全量数据都存储在高速缓存层,这两种缓存设计模式都可以有效地提高系统的性能,然而使用内存作为直接存储介质会带来较高的成本,因此适用于存储全量活跃数据场景。

(三) Cache-Aside 旁路缓存模式

Cache Aside Pattern 是一种在分布式系统中广泛采用的缓存和数据库协同工作策略。

在这个模式中,数据以数据库为主存储,缓存作为提升读取效率的辅助手段。

旁路缓存模式的读写流程如下:

  1. 读取数据时。
    • 首先尝试从缓存中获取数据;
    • 如果缓存命中,则直接返回;
    • 如果缓存未命中,从数据库中读取数据并将其放入缓存,最后返回给客户端。
  2. 写入数据时。
    • 首先,应用程序会更新数据库中的数据。
    • 然后,应用程序会删除缓存中的数据,或使得缓存中的数据失效。
    • 这样一来,后续的读请求将无法从缓存获取数据,从而迫使系统从数据库加载最新的数据并重新填充缓存。

在这里插入图片描述

这个过程需要注意两点:

  1. 缓存与数据库操作的先后顺序问题。
    • 必须应当使数据库操作在缓存操作之前完成,否则会导致数据不一致。
    • 如果先删除缓存,再更新数据库,有可能会导致缓存中存在脏数据。
    • 发生错误的情况:A 先删除缓存,然后 B 读取缓存发现未命中,此时 B 会将数据库中的数据更新至缓存,然后 A 再更新数据库。

在这里插入图片描述

  1. 更新数据时对缓存的处理。
    • 更新数据时,我们不能更新缓存,而应将缓存中对应的数据删除或使其失效。
    • 如果更新操作同时修改了数据库和缓存,则会导致数据不一致。
    • 发生错误的情况:A 先更新数据库,然后 B 更新数据库并先更新缓存,然后 A 再更新缓存。

在这里插入图片描述

相比于上面两种模式,旁路缓存模式中缓存是按需加载的,所以不会浪费宝贵的缓存空间存储未被访问的数据,只会缓存相对热点的数据,从而提升系统的整体性能。

由于缓存通常并不支持事务回滚,因此如果写入过程时数据库更新成功但缓存删除失败,则会导致数据不一致,因此我们需要对缓存数据合理设置过期时间,从而使得错误缓存能够及时被清除。

(四) Delay-Double-Delete 延迟双删缓存模式

旁路缓存设计模式中,读取数据库操作和更新缓存操作之间存在时间窗口,这有可能导致在窗口内有写请求发生,导致缓存与数据库数据不一致。

请看下面的例子,假设 A 读取数据同时 B 更新数据:

  • 线程 A 去缓存中读取数据,未命中;
  • 线程 A 取数据库中读取数据;
  • 线程 B 写入数据,删除缓存,此时数据库中数据为最新值;
  • 线程 A 写入缓存,缓存中数据为旧值。

在这种情况下,缓存与数据库中数据发生了不一致。解决方案有以下四种:

  • 对缓存中的数据设置合理的过期时间,即便缓存中存储了旧数据,也会在一段时间后自动过期。
  • 使用异步策略,使用 Canal 等工具监听数据库变化,然后投放入消息队列中异步删除缓存。
  • 使用删除重试策略,如果缓存删除失败,则再次尝试删除,直到成功为止。
  • 写入数据时,先更新数据库,再删除缓存,由于后面有可能有读请求将缓存更新为旧值,因此延迟一段时间再删除缓存。

其中最后一种方案又称为延迟双删缓存模式,这种模式存在一定争议,即如何保存未进行第二次延迟删除的命令。这会引发一系列的复杂问题。

缓存 Cache Miss 问题

缓存 Miss 问题是指缓存中没有命中的情况,主要有以下几种情况:

  1. 缓存穿透:当缓存和数据库中都没有该数据时,请求会穿透到数据库,导致数据库压力过大。
  2. 缓存雪崩:当缓存服务器重启或者大量缓存集中在某一时间段失效时,所有请求都会落到数据库上,造成数据库压力过大。
  3. 缓存击穿:当某个热点数据在缓存过期的一瞬间,大量请求同时访问该数据,导致数据库压力过大。

(一) 缓存穿透 Cache Penetration

缓存穿透是指查询一个一定不存在的数据(通常是恶意攻击),由于缓存是不命中时查询数据库,所以如果数据库中没有这个数据,每次查询都会被缓存认为是缓存穿透。

事实上,这样的无效请求给缓存和数据库都带来了巨大的压力。因此这样的数据理论上就不应该经过业务处理,我们通常需要在网关层进行无效请求过滤。

解决方案:

  1. 布隆过滤器 Bloom Filter

    • 布隆过滤器是一种牺牲空间换取时间和结果的技术
    • 布隆过滤器是一种基于 bitmap 配合一组哈希函数的概率型数据结构,它可以用于检索一个元素是否在一个集合中
    • 如果一个元素存在于集合中,那么布隆过滤器一定可以放行;如果不存在,布隆过滤器有可能不会放行,也有可能误判从而放行
    • 在项目上线之前,可以先用布隆过滤器对所有存在的数据进行预处理
    • 举例;某布隆过滤器由 10 个哈希函数和 10000 个 bit 组成
      • 事先对所有的元素进行 10 次哈希运算,并将得到的 10 个哈希值与 10000 个 bit 进行位运算,得到的结果存入布隆过滤器中
      • 当要判断某个元素是否存在于集合中时,需要对该元素进行 10 次哈希运算,并将得到的 10 个哈希值与 10000 个 bit 进行位运算
      • 如果结果有 0 则该元素一定不存在于集合中;如果结果全部为 1 则该元素可能存在于集合中,也可能不存在,但误判的概率较低
  2. 缓存空值 Null Cache

    • 前面提到,布隆过滤器可能会造成误判,导致部分恶意请求依然有可能穿透缓存。
    • 当缓存和数据库都没有该数据时,可以将空值也缓存一段时间,称为缓存空值。
    • 这样后续的恶意请求也会直接命中缓存,避免了穿透缓存。

(二) 缓存雪崩 Cache Avalanche

缓存雪崩是指缓存服务器重启或者大量缓存集中在某一时间段失效时,所有请求都会落到数据库上,造成数据库压力过大。

解决方案:

  1. 缓存失效时间设置随机或分散 Randomized Expiration

    • 我们假设数据在同一时间进入缓存,将这些数据的缓存失效时间设置随机或分散,可以避免缓存集中失效。
  2. 多级缓存 Multi-Level Caching

    • 使用多级缓存架构,避免缓存单点故障导致雪崩。
  3. 限流降级 Rate Limiting and Degradation

    • 当系统检测到雪崩即将发生时,可以通过限制请求流量或者降级服务保护数据库。

(三) 缓存击穿 Cache Breakdown

缓存击穿是指某个热点数据在缓存失效或过期的一瞬间,大量未命中缓存的请求同时访问该数据,导致数据库压力过大。

缓存击穿与缓存雪崩的区别:

  • 缓存击穿发生在某个热点数据的缓存失效或过期,这个热点数据本身就是高并发的,属于单点击穿。
  • 缓存雪崩是大量缓存数据在同一时间集体失效或过期,数据本身并发量并不高,但放到一起就是缓存雪崩。

解决方案:

  1. 加锁 Locking

    • 加锁可以保证大量未命中缓存的请求在同一时间只能有一个线程去查询数据库,从而避免缓存击穿。
    • 一般我们需要准备另一台 redis 专门用于抢锁,谁抢到锁就先处理请求并更新缓存,其他线程等待,或重试,或返回兜底数据。
  2. 热点数据预热 Preloading

    • 预热是指在系统启动时或热点数据失效之前,将热点数据加载到缓存中,避免缓存击穿。
    • 如何知道哪些数据是热点数据?可以用统计分析、日志分析等手段,通过各种各样的度量系统进行判断。
  3. 使用永不过期策略

    • 对于缓存数据,我们可以设置永不过期,彻底避免击穿问题。

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

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

相关文章

使用OpenCV和MediaPipe库——抽烟检测(姿态监控)

目录 抽烟检测的运用 1. 安全监控 (1) 公共场所禁烟监管 (2) 工业安全 2. 智能城市与执法 (1) 城市违章吸烟检测 (2) 无人值守管理 3. 健康管理与医疗 (1) 吸烟习惯分析 (2) 远程监护 4. AI 监控与商业分析 (1) 保险行业 (2) 商场营销 5. 技术实现 (1) 计算机视…

怎么有效降低知网AIGC率

在学术创作日益规范且数字化检测技术不断发展的当下,知网 AIGC 检测成为了众多创作者关注的焦点。许多人苦恼于如何有效降低知网 AIGC 率,让自己的作品在通过检测的同时,彰显出真实的创作水平与独特性。接下来,我们就深入探讨降低…

C语言每日一练——day_8

引言 针对初学者,每日练习几个题,快速上手C语言。第八天。(连续更新中) 采用在线OJ的形式 什么是在线OJ? 在线判题系统(英语:Online Judge,缩写OJ)是一种在编程竞赛中用…

Mac中nvm切换node版本失败,关闭终端再次打开还是之前的node

Mac中使用 nvm 管理 node 版本,在使用指令:nvm use XXX 切换版本之后。 关闭终端,再次打开,输入 node -v 还是得到之前的 node 版本。 原因: 在这里这个 default 中有个 node 的版本号,使用 nvm use 时&a…

更改 Windsuf 插件 Market

前言 之前一直用 VScode,现在全部迁移到 Windsuf 了,但是,Windsuf 默认的插件市场里没有我喜欢的主题……我又有点强迫症,所以,把Windsuf 默认的插件市场换成 VScode 的😑 不废话 原本的: 改…

Vue 过滤器深度解析与应用实践

文章目录 1. 过滤器概述1.1 核心概念1.2 过滤器生命周期 2. 过滤器基础2.1 过滤器定义2.2 过滤器使用 3. 过滤器高级用法3.1 链式调用3.2 参数传递3.3 动态过滤器 4. 过滤器应用场景4.1 文本格式化4.2 数字处理4.3 数据过滤 5. 性能优化与调试5.1 性能优化策略5.2 调试技巧 6. …

​AI时代到来,对电商来说是效率跃升,还是温水煮青蛙

​凌晨三点的义乌商贸城,95后创业者小王,静静地盯着屏幕上的AI工具,竟露出了笑容。这个月他的跨境玩具店销量提升了不少,从之前的状态翻了3倍;而且团队人数有所变化,从5人缩减到了2人(其中包括他…

Androidstudio实现一个app引导页(超详细)

文章目录 1. 功能需求2. 代码实现过程1. 创建布局文件2. 创建引导页的Adapter3. 实现引导页Activity4. 创建圆点指示器的Drawable5. 创建“立即体验”按钮的圆角背景 2.效果图 1. 功能需求 1、需要和原型图设计稿对应的元素保持一致的样式。 2、引导页需要隐藏导航栏&#xff…

[思考记录]关于AI辅助独立思考

本来是写两个反思类的记录,已经有了一些思路,并且都写了个开头。但手欠,去试着问了下AI,发现它的分析总结比我透彻。额......既然你这么厉害,那就你来,我向你学! 那么,后续我再做类似…

CVPR-2025 | 长程视觉语言导航平台与数据集:迈向复杂环境中的智能机器人

作者:Xinshuai Song, Weixing Chen, Yang Liu, Weikai Chen, Guanbin Li, Liang Lin 单位:中山大学,Independent Researcher,鹏城实验室 项目主页:https://hcplab-sysu.github.io/LH-VLN 论文地址:https…

Apifox Helper 自动生成API接口文档

在我们开发过程中我们在编写请求地址和编写请求参数的时候特别花费时间耗费了我们很多时间,作为一个程序员,更应该把精力时间集中在开发上, Apifox Helper 是 Apifox 团队针对 IntelliJ IDEA 环境所推出的插件,可以在 IDEA 环境中…

历年云南大学计算机复试上机真题

历年云南大学计算机复试机试真题 在线评测:传送门:pgcode.cn 喝饮料 题目描述 商店里有 n 中饮料,第 i 种饮料有 mi 毫升,价格为 wi。 小明现在手里有 x 元,他想吃尽量多的饮料,于是向你寻求帮助&#x…

Postman中Authorization和Headers的区别

案例 笔者在进行token验证的时候碰到的问题 一般如果是进行token验证,大部分是在Headers下面添加token名称及token的值 这样:后端提取请求头的token即可 还有一种是,左侧选择Bearer Token,右侧添加token的值,后端传递的 大概…

python使用openai的api的时候声明不要走系统代理,默认是走的

配置了以上的方式,还是不行。因为项目默认使用的是国内的大模型服务商,但是接口是和openapi通用的,所以可以直接使用,但是项目中有的链接还是要走系统代理的,所以就需要将两者区分开,配置openapi不走系统代…

【免费】1949-2020年各省人均GDP数据

1949-2020年各省人均GDP数据 1、时间:1952-2020年 2、来源:国家统计局、统计年鉴 3、指标:各省人均GDP 4、范围:31省 5、指标解释:人均GDP(Gross Domestic Product per capita)是指一个国家…

《Python实战进阶》No24: PyAutoGUI 实现桌面自动化

No24: PyAutoGUI 实现桌面自动化 摘要 PyAutoGUI 是一个跨平台的桌面自动化工具,能够模拟鼠标点击、键盘输入、屏幕截图与图像识别,适用于重复性桌面任务(如表单填写、游戏操作、批量文件处理)。本集通过代码截图输出日志的实战形…

功耗电流和耗电量的获取

1. 实验室环境: 在受控的实验条件下,我们使用 PowerMonitor 精确控制变量(如固定设备型号和系统版本、清理后台应用、设置恒定的亮度与音量、确保稳定的网络连接等),以获取高精度的电流测量数据,从而准确评…

医疗送药机器人“空间拓扑优化+动态算法决策+多级容错控制”三重链式编程技术解析与应用

一、引言 1.1 研究背景与意义 在医疗体系中,高效精准的药品配送是保障医疗服务质量和患者安全的关键环节。随着医疗技术的不断进步和医疗需求的日益增长,传统的人工送药方式逐渐暴露出诸多弊端,如配送效率低下、易受人为因素干扰导致错误率上升、人力成本高昂等。特别是在…

[CISCN 2022 初赛]ezpop(没成功复现)

打开在线环境可以看到&#xff1a; 记得之前做过一个类似的就是有点像照着漏洞去复现。应该可以直接在网上找到链子去打。 www.zip查看路由是 Index/test&#xff0c;然后 post 传参 a&#xff1a; exp&#xff08;参考了别的大神的wp&#xff09;&#xff1a; <?php //…

QT编程之QGIS

一、QGIS介绍 Quantum GIS&#xff08;QGIS&#xff09;是开源地理信息系统桌面软件&#xff0c;使用GNU&#xff08;General Public License&#xff09;授权&#xff0c; 属于 Open Source eospatial Foundation&#xff08; OSGeo &#xff09;的官方计划。在 GNU 授权下&am…