前言

缓存,几乎是现在互联网项目中最常见的一种加速工具了。 通过缓存,我们能大幅提升接口响应速度,减少数据库的访问压力,还能支撑各种复杂的业务功能,比如排行榜、风控系统、黑名单校验等等。

不管你用的是本地缓存,还是像 RedisMemcached 这样的分布式缓存,它们和 MySQL 这类数据库之间,都属于 “异地、异质存储” ——也就是说,它们不在一个地方,数据结构和操作方式也不一样。

在这里插入图片描述

这就带来一个问题:在分布式系统中,我们很难保证数据库和缓存在更新时 “要么一起成功,要么一起失败” 。一旦中间出错,就可能出现数据不一致——数据库是最新的,但缓存还是旧的;或者缓存更新了,但数据库失败了。

为了应对这种情况,业界衍生出了很多种“如何保持缓存和数据库数据一致性”的解决方案。这些方案在一致性保障、性能开销等方面各有优缺点。只有我们真正理解了这些方案的原理和适用场景,才能在面对实际复杂业务时,选出最合适的技术路径。

一、 缓存读写策略

在介绍数据库与缓存一致性方案之前,我们先来看一下经典的三种缓存读写策略,这三种策略是出现在计算机系统中的三大基本策略,而数据库与缓存一致性方案,也是基于这三种策略的思想,进行设计的。

🍎Cache Aside Pattern(旁路缓存模式)

在平时的开发中,我们最常用的一种缓存读写策略就是 Cache Aside Pattern(旁路缓存模式)。它特别适合读多写少的场景,比如商品详情页、用户资料页、排行榜等。

这种模式的特点是:缓存不是自动更新的,而是由应用服务自己“旁路”来操作缓存和数据库。而且,无论缓存和数据库怎么配合,最终还是以数据库的数据为准

📝 写数据:

  1. 先更新数据库:因为数据库才是最终的数据源,必须先保证它的数据正确。
  2. 再删除或更新缓存:确保下一次读取时不会拿到旧数据。

(有时为了简单或避免并发问题,写完数据库后会选择“删缓存”而不是“改缓存”,让下一次读请求自动加载最新数据。)

📖 读数据:

  1. 先从缓存里查,如果有,就直接返回,速度非常快。
  2. 如果缓存没命中(缓存穿透),就去查数据库;
  3. 查完数据库后,再把结果写入缓存,方便下次读用。

🍎Read/Write Through Pattern(读写穿透)

除了旁路缓存(Cache Aside),还有一种缓存策略叫做 Read/Write Through Pattern,中文通常称为读/写穿透。它的思路是:把缓存当作“主战场”,应用程序只和缓存打交道,缓存自己负责跟数据库同步。

也就是说,缓存成了真正的“前线”,数据库则被藏在了后面,由缓存服务来决定什么时候读写数据库。

这种模式在日常开发中其实不太常见,主要原因是我们常用的 Redis、Memcached 等分布式缓存,本身并不支持自动把数据写回数据库。所以这个模式更多出现在一些特定的场景或者缓存服务本身就集成了这种能力的系统中。

📝 写数据(Write Through):

  1. 如果缓存中不存在数据,就直接把数据写入数据库(有些实现也可能先写入缓存,然后由缓存去同步数据库);
  2. 如果缓存中有数据,就直接更新缓存,由缓存服务自动同步数据到数据库。

也就是说,写操作是走缓存 → 缓存再同步到数据库,这对应用开发者来说是“看不见的”。

📖 读数据(Read Through):

  1. 应用先从缓存中读取数据;
  2. 如果缓存中没命中,就自动从数据库加载,再由缓存服务把数据写入缓存,最后返回给应用。

在这个模式下,缓存系统不仅是加速器,还是“数据库代理”,自己负责读写落库逻辑,对调用方来说完全透明。

🔍 和 Cache Aside 有什么区别?

Read/Write Through 和 Cache Aside 看起来很像,但有一个核心差别:

  • Cache Aside 模式 中,缓存更新是由客户端(业务服务)来处理的
  • 而在 Read/Write Through 模式 中,缓存更新是由缓存系统自己处理的,对客户端是透明的。

可以理解为:Cache Aside 是“你自己去超市买东西”,而 Read/Write Through 是“你告诉助手你要什么,助手帮你搞定所有操作”。


🍎Write Behind Pattern/Write Back(异步缓存写入/写回)

除了读/写穿透(Read/Write Through),还有一种更激进的缓存写入策略,叫做 Write Behind Pattern(异步缓存写入/写回)

它和 Read/Write Through 很像,都是由缓存系统来负责数据库的读写工作,但它最大的不同在于写操作是“先写缓存,稍后再异步更新数据库”

也就是说:应用写数据时,只写到缓存里,数据库并不会立刻更新,而是缓存系统稍后“批量”写入数据库。

📝 写数据(Write Behind):

  1. 应用将数据写入缓存;
  2. 缓存服务暂时保留数据(比如放在内存队列里)
  3. 缓存服务在某个时间点,异步地、批量地把数据写入数据库

📖 读数据:

和其他模式一样,优先从缓存读,缓存未命中再从数据库加载。

⚠️ 优势与挑战:

优点:

  • 因为数据库的写入是延迟+批量的,写性能非常高
  • 适合高频更新的场景,比如点赞数、浏览量,不需要每次都写数据库。

挑战:

  • 数据一致性风险更大:如果还没来得及写入数据库,缓存服务就挂了,那这些数据可能就“丢了”;
  • 更复杂的故障恢复和数据容错机制(比如 WAL、落盘日志、数据回溯等)才能保证安全。

下面针对这三种策略,介绍一些更详细的方案。

二、缓存一致性方案

CAP

在聊缓存一致性方案之前,我们先来了解一个非常经典的分布式系统理论——CAP 定理,它对我们后续的讨论非常关键。

CAP 定理,又叫 布鲁尔定理(Brewer’s Theorem),是理论计算机科学中关于分布式系统的一个重要结论。它告诉我们:

一个分布式系统,不可能同时满足以下三件事,只能选其二。

  1. 一致性(Consistency)
    所有节点看到的数据必须是一样的。你读到的内容就是最新写入的结果,哪怕读的机器不同。

  2. 可用性(Availability)
    每次请求都必须有响应(不能返回超时或错误),哪怕返回的不是最新数据。

  3. 分区容错性(Partition Tolerance)
    系统在网络分区(比如服务之间通信延迟、网络中断)时,仍然能继续运作。

根据定理,分布式系统只能满足三项中的两项而不可能满足全部三项。理解CAP理论的最简单方式是想象两个节点分处分区两侧。允许至少一个节点更新状态会导致数据不一致,即丧失了C性质。如果为了保证数据一致性,将分区一侧的节点设置为不可用,那么又丧失了A性质。除非两个节点可以互相通信,才能既保证C又保证A,这又会导致丧失P性质。

而对于我们的缓存架构来说,分区容错性是我们必须保证的,那么,这是否代表,一致性和可用性无法同时保证呢?

让我们带着这个疑惑,来看一下缓存一致性方案。

2.1 Cache Aside Pattern

更新DB,再更新缓存

这种方式虽然保证了数据库数据的准确性,但也可能引发缓存和数据库不一致的问题。

举一个例子来说明:

假设有两个请求「A」和「B」,几乎同时对同一条数据进行更新。

  • 请求 A 先执行,将数据库中的数据更新为 1;
  • 然而,还没来得及更新缓存,请求 B 又将数据库的数据更新为 2,并紧接着更新缓存为 2;
  • 此时,A 继续完成它的流程,把缓存又更新成了 1。

在这里插入图片描述

最终,数据库的值是 2,而缓存中却是旧值 1 —— 出现了明显的数据不一致问题。

这种现象,从专业角度来看,就是一种脏写(Dirty Write)

即后写入的较新数据被前一个旧写操作覆盖,造成数据倒退。

在高并发写操作的场景下,这种问题极容易发生,严重时可能导致业务逻辑混乱,数据紊乱。


更新DB,再删除缓存

既然更新缓存会导致脏写问题,那我们是否可以选择不写缓存、只删除缓存,让读请求时自动重建缓存,从而避免脏写?看似可行,但这是否就万无一失了呢?

来看下面这个场景:

  • 请求A先去读缓存,发现缓存未命中,读取数据库的值为20
  • 与此同时,请求B更新数据库的值为21
  • 请求B继续删除缓存
  • 请求A回设缓存值为20
    在这里插入图片描述

最终结果:

  • 数据库是 21
  • 缓存是 20(请求 B 删除后导致缓存重建为旧值)

这就是典型的脏读问题:请求顺序错乱导致旧值覆盖新值。

虽然理论上存在这个问题,但在实际中它的发生概率非常低。因为:

  1. 数据库读操作通常比写操作快;
  2. 如果请求 A 在请求 B 之前完成了缓存写入,那请求 B 的删除操作不会影响后续的数据一致性;
  3. 即使不一致,也只是短暂的,后续请求会从数据库中重新拉取数据。

总结:

  • 这种「先更新数据库,再删除缓存」的方式可以大概率保证数据一致性
  • 配合合理的缓存过期时间,可实现最终一致性

但还没完,另一个风险点是:删除缓存失败

如果数据库更新成功,但缓存删除失败,旧缓存仍然存在,导致数据不一致。这是分布式系统中典型的部分成功问题。

在这里插入图片描述

如何解决?

  • 重试机制虽然可以一定程度缓解,但难以控制重试次数,太少不稳,太多影响接口响应时间;
  • 更优方案是:异步可靠删除缓存

做法是:

  • 将删除缓存操作写入消息队列任务队列中,由后台服务异步拉取并执行;
  • 配合失败重试与日志告警机制,确保缓存删除最终成功。

这样既保证了数据一致性,又不会阻塞主业务流程,是更推荐的实践方式。


更新DB,异步删除缓存

我们在更新数据库后删除缓存时,可以通过异步方式来处理缓存删除操作。常见的异步实现方式包括以下三种:

  • 线程池异步执行删除任务
  • 消息队列异步投递删除请求
  • 基于数据库 Binlog 日志消费(如 Canal)

前两种方式虽然常用,但它们对业务代码侵入较大:每当更新数据库时,开发者都必须显式编写删除缓存的逻辑,容易遗漏、维护成本高。

相比之下,基于 Binlog 的异步删除方式是当前业界较为推荐的方案。其核心流程如下:

  1. 数据库完成写入
  2. Canal 监听 Binlog 日志变化并解析
  3. 将变化内容发送到消息队列
  4. MQ 消费者接收到消息,触发缓存删除

在这里插入图片描述

由于 MQ 的可靠投递机制,能大幅提升缓存删除的成功率,从而增强缓存与数据库的一致性。


延伸思考

1. 为什么选择删除缓存而不是更新缓存?
因为更新缓存容易产生并发乱序问题。例如:一个旧值覆盖了新值,造成脏写,难以控制。而删除缓存是幂等操作,天然具备更好的一致性保障。

2. 有没有办法不删除缓存也能解决脏写?
有,比如加分布式锁,通过串行化更新操作防止乱序。但分布式锁使用复杂、对性能影响大,一般只在强一致场景中才推荐。

3. 删除缓存是否也有副作用?

是的,主要有两点:

  • 删除后首次访问会触发缓存重建,若是热点数据(hotkey),可能造成缓存击穿
  • 一部分请求会落到数据库,导致缓存命中率下降,影响性能表现。

4. 异步机制会有什么问题?
异步天然存在延迟,在这段时间内,缓存和数据库可能处于不一致状态。不过通常这种不一致窗口较小,可通过优化消费速率、重试机制等方式缓解。

2.2 Read/Write Through Pattern

虽然这种策略看起来与旁路缓存(Cache Aside Pattern)类似,但两者之间还是存在一些区别。最主要的不同点在于:该方案并不是由业务逻辑直接控制缓存的写入,而是由专门的缓存服务(如 CacheSetter)负责完成缓存回源与更新。

正因为如此,这种策略更多的是一种架构层面的演进,并不是一种新的缓存一致性策略,因此我们在本文中不再对其展开详细讨论。

2.3 Write Behind Pattern

在前文中,我们介绍了多种缓存一致性策略,而这一节要讨论的“先更新缓存,异步更新数据库”的方式,则属于Write Behind(异步缓存写入/写回)模式,它与前述策略的最大区别是:只更新缓存,不立即更新数据库,而是通过异步手段,延迟、批量地将数据刷新到数据库中。

写流程:

  1. 客户端写入请求直接更新缓存;
  2. 同步或异步地将修改写入队列(如消息队列、内存队列);
  3. 后台线程池 / MQ 消费者 / 定时任务从队列中批量取出数据写入数据库。

读流程:

  1. 优先从缓存中读取数据;
  2. 若缓存不存在,则从数据库读取,并同步回写缓存。

该方案的优势在于:

  • 写吞吐能力强:所有写操作都直接打到缓存,极大减轻数据库写压力;
  • 数据即时可读:用户写入后立刻可读缓存,体验更好;
  • 适合高并发写入场景:如秒杀库存、日志上报、计数器类应用等。

⚠️存在的风险与缺陷:

  • 数据库和缓存可能不一致:缓存中的数据是最新的,而数据库是延迟更新;
  • 数据可能丢失:如果缓存宕机、消息队列丢失消息、服务重启等,都可能导致更新未写入数据库;
  • 一致性难以保障:特别在关键业务中,数据丢失可能带来严重问题。

方案对比汇总

策略存在问题优点适用场景
更新数据库 → 更新缓存并发可能导致脏写缓存命中率较高对一致性要求不高,注重命中率
更新数据库 → 更新缓存(加锁)分布式锁影响性能保证强一致性写请求较少,强一致性场景
更新数据库 → 删除缓存命中率略降,少数并发异常可能简洁,最终一致性好主流方案,适用于大多数业务
更新数据库 → 异步删除缓存有延迟窗口,不是强一致性能优,兼顾一致性和吞吐主流推荐方案,适合大多数系统
更新缓存 → 异步更新数据库数据可能丢失,无法保障一致性写性能极强,延迟低日志、计数器、非关键业务

三、真实业务中的缓存一致性实践

某手缓存方案

在某手,目前主流的缓存架构方案是将数据库中的热点数据写入到 Memcached中,以加速读请求,降低数据库压力。为确保缓存与数据库之间的数据一致性,采用的是 Cache Aside Pattern(旁路缓存模式) 的一种变种策略:
即在数据更新时,先更新数据库,再通过异步方式消费 binlog 日志,删除或更新对应缓存。

在这里插入图片描述

📖 读流程

  1. 先查缓存:优先从缓存(Memcached)中查询目标数据。
  2. 未命中则回源:如果缓存未命中,则调用 CacheSetter 服务进行回源。
  3. 读取并更新缓存:CacheSetter 从数据库中读取最新数据并更新缓存,再返回结果。

✍️ 写流程

  1. 更新数据库:应用服务处理用户写请求,直接更新数据库。
  2. 写请求结束:数据库更新成功后,用户请求结束。
  3. 异步同步缓存
    • kbus 服务监听数据库 binlog 变更;
    • 收到变更后,异步调用 CacheSetter
    • CacheSetter 再从数据库中读取最新值,更新缓存。

✅ CacheSetter 如何保证缓存一致性?

由于异步更新存在并发修改缓存的可能,CacheSetter 被设计为一个特殊的 RPC 服务,核心职责是 在高并发场景下,避免缓存更新过程中的“脏写”问题,确保最终一致性。

CacheSetter 保证针对同一id,同一时间,只有单一线程,在更新缓存,因此可以 避免并发问题 ,可以保证了缓存的 最终一致性 。

具体机制包括:

  1. 同 ID 路由固定:客户端请求使用一致性Hash算法,确保相同 ID 的请求路由到固定的 CacheSetter 实例,避免多实例并发更新同一份缓存。
  2. 并发访问收敛CacheSetter 内部通过 CountDownLatch 等并发控制手段,确保同一时刻对于同一 ID 的并发 load 请求,只会命中一次DB,其他线程等待结果复用即可。

当一台实例上一个key已经在进行load的操作的时候,如果这时候又有这个key的请求要load cache,此时这次请求的这个key将不会在进行load操作。CacheSetter会为某个key分配一个 CountDownLatch ,当某个key请求CacheSetter时,会先检查下当前是否为这个key分配了CountDownLatch,如果已经分配了,说明这个key已经在loading了,就不再执行load操作了,只会通过CountDownLatch.await,在这个key load完成之后再返回;如果没有分配,就创建一个新的CountDownLatch,并将id和该CountDownLatch保存到map,等到load操作执行完,会执行CountDownLatch.countDown操作,并从map中移除该key和对应的CountDownLatch。

当然,这种方案依赖于异步 binlog 消费流程,所以不能保证实时一致性,但在大多数读多写少的场景下效果良好。

四、总结:缓存与数据库一致性策略的本质与抉择

在每种方案中,我们结合其在一致性与性能方面的权衡,明确了各自适用的业务场景。通过对比可以看出,缓存与数据库一致性问题的根本原因主要有两个:

  1. 指令乱序问题:即多个请求之间操作缺乏原子性保障;
  2. 分布式系统中的不确定性:包括网络失败、节点宕机等,导致单个请求的多个操作无法组成原子事务。

所有的一致性方案,实质上就是围绕着如何缓解这两大问题,进行策略设计与技术落地。

回到最初的问题:CAP 中的 C 和 A 是否能兼得?

经过前文的分析可以发现,在实际场景中:

  • 当追求强一致性(Consistency)时,往往需要加锁、顺序执行或等待异步流程完成,带来的副作用就是性能下降,可用性降低
  • 而当强调可用性(Availability)与高性能时,则必然在一致性上做出一定让步,常见的表现如最终一致性顺序一致性等。

写在最后

缓存与数据库一致性问题没有“银弹”式的完美解决方案。所有架构设计都是权衡的艺术。技术选型和策略制定,应该回归到业务的实际需求、系统的承载能力、以及对一致性与性能的优先级判断上。

愿本文内容,能为你在系统设计与架构演进过程中提供一些参考与思考。

五、参考文献:

CAP-Wiki百科
三种常用的缓存读写策略详解
数据库和缓存如何保证一致性
缓存和数据一致性问题,看这篇就够了

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

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

相关文章

主流Java Redis客户端深度对比:Jedis、Lettuce与Redisson性能特性全解析

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 持续学习,不断…

AI问答系统完整架构规划文档

📋 目录 现有代码架构分析 AI核心组件缺口分析 完整技术架构设计 开发路线图 技术实现要点 🏗️ 现有代码架构分析 当前项目结构 ai问答/ ├── main.py # FastAPI服务入口,API路由 ├── model.py # 基础LLM模型加载与推理 ├── rag.py …

圆柱电池自动分选机:全流程自动化检测的革新之路

在新能源产业快速发展的背景下,圆柱电池作为动力电池和储能领域的核心组件,其生产效率与质量把控至关重要。圆柱电池自动分选机的出现,通过全流程自动化检测技术,为电池制造与分选环节提供了高效、精准的解决方案。传统电池分选依…

leetcode 1695. 删除子数组的最大得分 中等

给你一个正整数数组 nums ,请你从中删除一个含有 若干不同元素 的子数组。删除子数组的 得分 就是子数组各元素之 和 。返回 只删除一个 子数组可获得的 最大得分 。如果数组 b 是数组 a 的一个连续子序列,即如果它等于 a[l],a[l1],...,a[r] &#xff0c…

netty的编解码器,以及内置的编解码器

一、编码器和解码器 1、什么是编码和解码 解码常用于入站操作,将字节转换为消息。编码用于出站,将消息转换为字节流 2、解码器ByteToMessageDecoder和ReplayingDecoder,ReplayingDecoder扩展了ByteToMessageDecoder类,使得我们不必…

一个基于现代C++智能指针的优雅内存管理解决方案

目录 问题陈述 (Problem Statement) 1.1 问题背景与动机1.2 问题复杂性分析1.3 传统解决方案的局限性1.4 目标需求定义 预备知识 (Preliminaries) 2.1 C智能指针基础2.2 循环引用问题详解2.3 自定义删除器2.4 引用计数机制深入理解 核心解决方案 (Core Solution) 3.1 设计思路…

LabVIEW单片机温控

基于 LabVIEW 与单片机设计温度控制系统,整合硬件电路、串口通信、控制算法及监控功能,适用于教学实验及中小型设备温控场景。系统以低成本实现高精度温控,为同类控制系统设计提供参考。应用场景教学场景:作为自动化专业综合实验项…

【初识数据结构】CS61B中的最小生成树问题

本教程总结CS61B 关于图章节中的最小生成树(Minimum Spanning Trees, MST)问题,以及对应的的算法什么是最小生成树(MST) 考虑这样一个问题,给你一个无向图,你能不能找出这个图中的一组边&#x…

vue apk返回键不好使

在 Android 设备上,你可以通过监听物理返回键来实现特定的逻辑。这可以通过在 Vue 组件中添加一个事件监听器来实现:mounted() {this.$once(hook:beforeDestroy, () > {if (document.removeEventListener) {document.removeEventListener(backbutton,…

Ubuntu 22.04 安装 MySQL 8.0 完整步骤文档

1、安装 1.1、下载 cd /usr/local/在 /usr/local/ 下执行,下载资源包,可以本地下载上传 wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.32-linux-glibc2.12-x86_64.tar.xz1.2、解压安装 tar -Jxvf mysql-8.0.32-linux-glibc2.…

Docker,其他机器下载镜像并copy到目标机器导入docker镜像

Docker,其他机器下载镜像并copy到目标机器导入docker镜像源机器 【下载镜像】目标机器slave1 【无法下载镜像】步骤 1:在网络正常的机器(cg)上下载镜像,导出镜像到指定路径# 1. 下载镜像docker pull ubuntu:20.04# 2.…

基于现代R语言【Tidyverse、Tidymodel】的机器学习方法与案例分析

机器学习已经成为继理论、实验和数值计算之后的科研“第四范式”,是发现新规律,总结和分析实验结果的利器。机器学习涉及的理论和方法繁多,编程相当复杂,一直是阻碍机器学习大范围应用的主要困难之一,由此诞生了Python…

如何将 git 远程 URL 从 https 更改为 ssh

在项目开发中,使用 SSH 连接 Git 仓库可以提高安全性和便利性。本文将指导你如何将 Git 远程 URL 从 HTTPS 更改为 SSH。操作指南步骤 1: 查看当前远程 URL首先,确认当前的远程 URL 使用的是 https。打开终端并输入以下命令:git remote -v如&…

PyCharm 高效入门指南(核心模块详解二)

四、生产力工具集成PyCharm 不仅仅是 Python 编辑器,更是集成了多种开发工具的综合平台。通过内置的生产力工具,开发者可以在一个界面内完成数据库操作、科学计算、远程开发和测试等全流程工作,避免工具切换带来的效率损耗。4.1 数据库工具链…

WebkitSpeechRecognition 语音识别

JavaScript WebkitSpeechRecognition:使用语音识别技术增强 Web 应用程序 WebkitSpeechRecognition 是一种 JavaScript API,它可以让您的 Web 应用程序使用语音识别技术。使用 WebkitSpeechRecognition,您可以让用户通过说话来与您的 Web 应用程序进行交互,这可以使您的应…

CUDA C++核心库(CCCL)

文章目录CUDA C核心库(CCCL)核心库介绍CUDA C 开发工具的层级范围各层级工具的具体内容Thrust自动内存管理类型安全自定义分配器(页锁定内存)高级API替代底层操作thrust::transform基本使用几种执行策略iteratorload_cs高效索引md…

MySQL InnoDB存储引擎深度解析:从原理到优化

InnoDB的优势InnoDB之所以成为众多应用的首选,主要得益于以下几个显著优势:事务支持:InnoDB是MySQL中唯一支持ACID(原子性、一致性、隔离性、持久性)事务的存储引擎。它通过日志和锁机制确保事务的完整性,这…

LLM评测框架Ragas:Natural Language Comparison指标(解决了Ollama推理框架不支持的问题)

Factural Correctness Factural Correctness是事实正确性是评价LLM生成的反馈和reference的事实正确性。该指标用于确定生成的响应与参考文献的一致程度。Factural Correctness取值在0到1之间,越接近于1结果越好。 为了衡量回应和参考文献之间的一致性,该指标使用 LLM 首先将…

HTTP 协议常见字段(请求头/响应头)

HTTP(HyperText Transfer Protocol)协议通过 请求头(Request Headers) 和 响应头(Response Headers) 传递元数据。以下是 最常见的 HTTP 字段 及其作用:1. 通用字段(请求和响应均可使…

期货配资软件开发注意事项?

期货配资软件开发 期货配资软件开发涉及多个核心模块,包括资金管理、风险控制、交易接口、用户权限管理等。此类系统需符合金融监管要求,确保资金安全与数据合规。开发过程中需优先考虑高并发、低延迟及系统稳定性。期货资管系统平台搭建方案架构设计 采…