news 2026/5/17 8:08:49

Redis增强工具包:封装分布式锁、缓存模板与监控的最佳实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis增强工具包:封装分布式锁、缓存模板与监控的最佳实践

1. 项目概述:一个Redis开发者的“瑞士军刀”

在分布式系统和高并发场景下,Redis几乎成了标配。但用久了你会发现,官方客户端虽然稳定,但在日常开发、调试、运维中,总有些“不够顺手”的地方。比如,想批量按模式删除一批Key,得写个脚本;想直观地监控某个Key的变化趋势,得依赖第三方工具;想在代码里优雅地处理缓存穿透、雪崩,又得自己造轮子。SKY-lv/redis-helper这个项目,就是冲着解决这些“痒点”来的。你可以把它理解为一个增强版的Redis客户端工具包,或者一个面向开发者的“Redis瑞士军刀”。它并非要替代JedisLettuceRedisson,而是在它们之上,封装了更贴近业务开发场景的便捷操作、监控能力和最佳实践模板。

这个工具的核心用户,是那些每天都要和Redis打交道的后端开发者、架构师以及运维工程师。如果你经常需要写一些重复性的Redis操作脚本,或者团队内部缺乏统一的缓存使用规范,那么这个项目提供的思路和实现,会给你带来不少启发和直接的便利。它试图将散落在各处的Redis使用经验,沉淀成可复用的代码,让缓存用得更加高效、安全和省心。

2. 核心功能模块深度解析

2.1 增强型操作封装:告别繁琐的原生命令

Redis原生命令虽然强大,但直接使用往往比较底层。redis-helper在这一层做了大量工作,将常见但繁琐的操作封装成简洁的方法。

2.1.1 模式化操作与批量处理

最典型的例子就是Key的批量删除。原生KEYS pattern命令在生产环境是禁用的,因为它会阻塞Redis单线程,可能导致服务卡顿。通常的替代方案是使用SCAN命令迭代。但每次都要写SCAN循环,很麻烦。redis-helper很可能提供了一个deleteByPattern(String pattern)方法,内部安全地使用SCAN进行迭代删除,并可能提供了可配置的批次大小,避免单次操作数据量过大。

// 假设的API示例 redisHelper.deleteByPattern(“user:session:*”);

除了删除,批量获取、批量设置带有复杂数据结构(如Hash、List)的Key,也是常见需求。项目可能会提供mGetByPatternpipeline的增强封装,将模式匹配与流水线操作结合,大幅提升批量操作效率。

注意:即使封装了SCAN,批量删除大量Key仍然需要谨慎。最好在业务低峰期执行,并关注Redis的CPU和内存监控。对于海量Key的删除,可以考虑使用UNLINK命令(非阻塞删除)的封装,如果Redis版本支持的话。

2.1.2 分布式锁的“一站式”解决方案

分布式锁是Redis的经典应用场景,但自己实现一个健壮的锁需要考虑很多细节:锁超时、续期(看门狗)、可重入性、原子性释放等。redis-helper极有可能内置了一个经过生产验证的分布式锁实现。

它可能基于SET key value NX PX timeout命令,并集成了以下特性:

  1. 自动续期:后台线程为持有锁的客户端续期,防止业务执行时间超过锁超时时间导致的锁失效。
  2. 可重入:同一线程可多次获取锁,通过ThreadLocal或客户端ID记录重入次数。
  3. 防误删:释放锁时检查value是否为本客户端设置的值(通常用UUID+线程ID),避免释放其他客户端的锁。这需要使用Lua脚本保证原子性。
  4. 多种锁类型:可能提供公平锁、读写锁等更复杂的锁语义。
// 假设的锁使用示例 try (DistributedLock lock = redisHelper.acquireLock(“order:create:” + orderId, 30000)) { if (lock != null) { // 执行业务逻辑 createOrder(); } else { throw new BusyException(“系统繁忙,请稍后重试”); } } // 自动释放锁

这个封装让开发者从复杂的锁细节中解脱出来,只需关注业务逻辑,同时保证了锁的安全性和可靠性。

2.1.3 复杂数据结构的便捷访问

对于Hash、ZSet等结构,有时我们需要进行一些复合操作。例如,更新Hash中某个字段的同时,获取更新前的值,并记录操作日志。原生命令需要组合使用。redis-helper可能会提供一些语法糖式的方法。

例如,一个hashFetchAndUpdate方法,内部用Lua脚本实现原子性的“读-改”操作:

local oldValue = redis.call(‘HGET’, KEYS[1], ARGV[1]) redis.call(‘HSET’, KEYS[1], ARGV[1], ARGV[2]) return oldValue

这样的封装保证了操作的原子性,避免了并发问题,同时简化了客户端代码。

2.2 监控与诊断集成:让缓存状态一目了然

缓存问题排查往往很头疼,redis-helper可能内置了轻量级的监控能力,帮助开发者快速定位问题。

2.2.1 Key级访问监控与热点发现

它可以通过AOP(面向切面编程)或代理模式,无侵入式地拦截对指定Key模式(如product:info:*)的访问。记录访问频率、响应时间、甚至调用链。这些数据可以输出到日志文件,或与微服务的监控系统(如Prometheus)集成,形成监控指标。

例如,你可以在配置中指定:

redis-helper: monitor: patterns: - “hot:product:*” metrics-output: prometheus # 或 log

这样,你就能在Grafana上看到一个名为redis_key_access_count{pattern=“hot:product:*”}的指标,实时掌握热点Key的动态。这对于发现意料之外的热点、预防缓存击穿非常有帮助。

2.2.2 慢查询自动捕获与报告

虽然Redis有SLOWLOG命令,但需要手动查询。redis-helper可以定期(例如每分钟)拉取Redis慢查询日志,解析并上报到监控系统或发送告警。它能帮你发现哪些复杂命令(如HGETALL一个大Hash,SORT一个大集合)正在拖慢Redis,从而及时优化业务代码或数据结构设计。

2.2.3 客户端连接与资源监控

它可能还封装了INFO命令的部分关键信息,如连接数、内存使用率、键空间信息等,并以友好的方式暴露给应用程序,方便在健康检查接口或管理后台中展示应用自身的Redis客户端状态。

2.3 缓存策略模板与防踩坑实践

这是redis-helper可能最具价值的部分之一:它不止提供工具,还提供“最佳实践”的代码实现。

2.3.1 标准缓存查询模板(Cache-Aside)

它可能提供了一个通用的CacheTemplate类,实现了标准的“旁路缓存”模式:

public <T> T executeWithCache(String key, Class<T> type, long ttl, CacheLoader<T> loader) { // 1. 查缓存 T value = redisHelper.get(key, type); if (value != null) { return value; } // 2. 缓存未命中,查数据库(加载器由业务提供) value = loader.load(); if (value != null) { // 3. 回填缓存,并设置TTL redisHelper.setex(key, value, ttl); } return value; }

这个模板自动处理了缓存空值(防止缓存穿透)、并发情况下的重复数据库查询(使用分布式锁或本地互斥锁)等细节。业务开发者只需关注loader的实现,大大减少了样板代码和出错概率。

2.3.2 缓存穿透、雪崩、击穿的防御实现

  • 穿透防御:在CacheTemplate中,对数据库也查不到的“空结果”进行短时间缓存(如设置一个特殊的占位符和2分钟TTL),避免恶意请求反复击穿到数据库。
  • 雪崩防御:在设置缓存TTL时,引入一个随机抖动值(例如,基础TTL是3600秒,实际TTL设置为3600 ± 300秒),避免大量Key在同一时刻失效,导致请求洪峰压垮数据库。
  • 击穿防御:在CacheTemplate的加载数据库环节,集成前面提到的分布式锁,确保对于同一个热点Key,只有一个线程去数据库加载,其他线程等待并复用结果。

2.3.3 本地二级缓存(Caffeine)集成

对于极端热点数据,频繁访问Redis也会有网络开销。redis-helper可能提供了与本地缓存(如Caffeine)的透明集成。它实现了一个两级缓存(L1本地,L2 Redis)的管理器,自动处理本地缓存的过期、更新和与Redis的数据一致性(通常采用发布订阅机制或定时刷新来保证最终一致)。这对于“读多写少”且数据量不大的全局配置类信息,性能提升非常显著。

3. 项目架构与核心实现剖析

3.1 整体设计:松耦合与可插拔

一个优秀的工具库,其架构设计必须保持灵活。redis-helper很可能采用了“核心接口 + 多种实现”的设计模式。

3.1.1 抽象接口层

定义了一系列核心操作接口,如CacheOperationsDistributedLockRedisMonitor。这些接口不依赖任何具体的Redis客户端(Jedis/Lettuce)。这使得库的核心逻辑保持稳定和可测试。

3.1.2 客户端适配层

针对不同的Redis客户端(JedisClientAdapter,LettuceClientAdapter)提供实现。这些适配器负责将接口方法翻译成底层客户端的原生调用。通过Spring的自动配置或工厂模式,可以根据项目依赖自动选择或由用户配置使用哪个适配器。这种设计让项目能兼容不同的技术栈,使用者如果从Jedis迁移到Lettuce,业务代码几乎无需改动。

3.1.3 功能模块层

各个增强功能(锁、监控、模板)作为独立的模块,依赖抽象接口层和适配层。它们之间也尽可能解耦。例如,监控模块通过监听操作接口的调用事件来收集指标,而不需要修改操作模块的代码。这种设计便于使用者按需引入功能,减少不必要的依赖。

3.2 关键实现细节与源码级思考

3.2.1 分布式锁的看门狗机制实现

锁的自动续期(看门狗)是保证锁安全的关键。一个可靠的实现通常包含以下组件:

  1. 续期任务调度:在获取锁成功后,启动一个后台的定时任务(使用ScheduledExecutorService)。这个任务的周期应远小于锁的超时时间(例如,锁超时30秒,每10秒续期一次)。
  2. 续期逻辑:续期任务执行一段Lua脚本,检查锁的value是否仍属于本客户端,如果是,则重置其过期时间。脚本必须保证原子性。
  3. 任务生命周期管理:锁释放时(包括正常释放和异常释放),必须能取消对应的续期任务,防止资源泄漏。这通常需要将锁实例与续期任务ID进行绑定,并在finally块或锁对象的close()方法中确保任务被停止。
  4. 客户端标识:为了在集群环境下也能正确识别客户端,value不能只用线程ID,通常结合客户端实例的唯一ID(如UUID)和线程ID。

3.2.2 监控数据的收集与聚合

无侵入式监控通常通过动态代理或字节码增强(如使用ByteBuddy)来实现。以AOP为例,可以定义一个切面,拦截所有通过redis-helper接口执行的操作。

@Aspect @Component public class RedisOperationMonitorAspect { @Around(“execution(* com.sky.redis.helper.core.CacheOperations.*(..))”) public Object monitor(ProceedingJoinPoint pjp) throws Throwable { long start = System.currentTimeMillis(); String methodName = pjp.getSignature().getName(); Object[] args = pjp.getArgs(); // 提取Key模式等信息 try { Object result = pjp.proceed(); long duration = System.currentTimeMillis() - start; // 记录成功指标:methodName, keyPattern, duration, “success” metricsRecorder.record(methodName, keyPattern, duration, “success”); return result; } catch (Exception e) { // 记录失败指标 metricsRecorder.record(methodName, keyPattern, “failure”); throw e; } } }

收集到的原始数据点需要聚合,以避免产生海量时间序列数据。例如,每10秒将“user:*”模式下的所有GET操作次数求和,作为一个数据点上报。这通常在内存中通过一个滑动窗口聚合器来完成。

3.2.3 缓存模板的并发控制

在缓存失效瞬间,大量请求涌入导致所有请求都去查数据库,这就是缓存击穿。CacheTemplate内部的并发控制机制至关重要。有两种常见思路:

  1. 分布式锁:如前所述,使用Redis分布式锁,只让一个请求去加载数据。其他请求等待锁释放后读取缓存。优点是保证绝对的单线程加载,缺点是增加了Redis的负担和请求延迟。
  2. 本地互斥锁(Guava Cache的LoadingCache思路):对于同一个Key,在应用本地使用ConcurrentHashMap存储一个“正在加载”的Future对象。第一个请求创建加载任务(Future),后续请求直接获取这个Future并等待其结果。优点是性能极高,避免了分布式锁的网络开销;缺点是在集群多实例环境下,每个实例可能都会去加载一次,对于数据库的压力是实例数倍,适用于数据库扛得住或数据一致性要求不严格的场景。redis-helper可能会提供这两种策略的选项。

4. 集成使用与生产环境配置指南

4.1 快速入门与基础配置

假设项目通过Maven引入,首先需要添加依赖(版本请根据实际情况调整):

<dependency> <groupId>com.github.sky-lv</groupId> <artifactId>redis-helper-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency>

对于Spring Boot项目,大多数配置可以自动完成。你只需要在application.yml中配置基本的Redis连接信息,以及redis-helper的扩展功能开关:

spring: redis: host: localhost port: 6379 password: database: 0 sky: redis-helper: enabled: true # 锁配置 lock: default-lease-time: 30000 # 默认锁持有时间(ms) watch-dog-interval: 10000 # 看门狗续期间隔(ms) # 监控配置 monitor: enabled: true include-patterns: “cache:user:*, cache:product:*” # 监控的Key模式 exclude-patterns: “cache:temp:*” # 排除的Key模式 metrics-export-interval: 60s # 指标导出间隔 # 缓存模板配置 cache-template: default-ttl: 3600s # 默认缓存过期时间 enable-null-cache: true # 是否缓存空值 null-cache-ttl: 120s # 空值缓存时间

配置完成后,你就可以在Spring管理的Bean中直接注入RedisHelper或更具体的CacheTemplateDistributedLockFactory等组件开始使用了。

4.2 高级特性配置与调优

4.2.1 连接池与客户端调优

redis-helper底层依赖的Jedis/Lettuce连接池参数对性能影响巨大。建议根据实际压测结果调整:

spring: redis: lettuce: pool: max-active: 50 # 最大连接数,根据应用实例数和QPS估算 max-idle: 20 min-idle: 5 max-wait: 1000ms # 获取连接最大等待时间 timeout: 2000ms # 命令超时时间

对于Lettuce,还可以开启共享连接(shareNativeConnection)来减少线程资源消耗。对于读写分离或集群模式,需要在配置中指定完整的节点信息。

4.2.2 监控数据输出与告警集成

监控数据可以输出到多个目的地:

  • 日志文件:配置为JSON格式,便于被ELK(Elasticsearch, Logstash, Kibana)或类似日志平台采集分析。
  • Micrometer/Prometheus:这是与云原生监控栈集成的标准方式。确保项目引入了micrometer-registry-prometheus依赖,redis-helper的指标会自动通过/actuator/prometheus端点暴露。你可以在Grafana中创建仪表盘,监控缓存命中率、命令延迟、热点Key等。
  • 自定义上报:你可以实现MetricsReporter接口,将数据发送到内部监控系统或阿里云SLS等商业服务。

基于这些指标,在Prometheus Alertmanager中配置告警规则,例如:

- alert: RedisCacheHitRateLow expr: rate(redis_helper_cache_hits_total[5m]) / rate(redis_helper_cache_requests_total[5m]) < 0.8 for: 5m labels: severity: warning annotations: summary: “缓存命中率过低 (实例 {{ $labels.instance }})” description: “过去5分钟,缓存命中率低于80%,当前值为 {{ $value }}。”

4.2.3 多级缓存配置

如果启用了本地二级缓存,需要仔细配置本地缓存的大小和过期策略,避免本地缓存占用过多堆内存或持有过期的脏数据。

sky: redis-helper: local-cache: enabled: true type: caffeine caffeine: spec: “maximumSize=10000, expireAfterWrite=10m, recordStats” # 一致性策略:定时刷新或发布订阅 consistency: mode: refresh # 或 pubsub refresh-interval: 5m # 定时刷新模式下,刷新间隔

使用“发布订阅”模式一致性更好,但架构更复杂,需要Redis支持Pub/Sub,且所有应用实例都要订阅。对于配置类数据,“定时刷新”是更简单实用的选择。

5. 生产环境常见问题与排查手册

5.1 性能与稳定性问题

5.1.1 现象:应用响应变慢,Redis CPU持续偏高。

  • 排查步骤
    1. 检查慢查询:使用redis-helper的慢查询日志功能,或直接连接Redis执行SLOWLOG GET 10,查看最近是否有复杂命令。
    2. 分析监控指标:查看redis_helper_command_duration_seconds等指标,定位是哪个操作、哪个Key模式延迟高。
    3. 检查大Key:使用redis-helper可能提供的scanBigKeys工具方法,或使用redis-cli --bigkeys命令,找出内存占用过大的Key(如巨大的Hash、List)。
    4. 检查连接池:查看应用日志是否有获取连接超时的错误。通过INFO clients命令查看Redis端的连接数是否异常增多。
  • 解决方案
    • 针对慢查询/大Key:优化数据结构。例如,将大Hash拆分成多个小Hash;使用HSCAN替代HGETALL;将长List分页。
    • 针对连接池:调整连接池参数,确保max-active足够但不过大。检查是否有连接泄漏(未正确关闭)。
    • 启用管道/批量操作:对于需要多次往返的连续操作,使用redis-helper封装的管道(pipeline)方法。

5.1.2 现象:缓存命中率突然下降。

  • 排查步骤
    1. 确认下降范围:是全局下降还是某个特定Key模式下降?通过监控面板查看细分指标。
    2. 检查缓存过期策略:是否发生了“缓存雪崩”?检查大量Key是否设置了相同或接近的TTL。
    3. 检查业务逻辑:是否有新的代码发布,导致缓存Key生成规则改变或缓存写入被跳过?
    4. 检查内存淘汰:执行INFO memory,查看used_memory是否接近maxmemory,以及evicted_keys是否持续增长。这表示Redis因内存不足正在主动淘汰Key。
  • 解决方案
    • 避免雪崩:启用redis-helper缓存模板中的TTL随机抖动功能。
    • 优化内存:对于被淘汰的Key,分析其价值。如果是重要数据,考虑增加Redis内存或优化数据结构减少内存占用;如果是临时数据,可以适当缩短其TTL。
    • 排查业务代码:回滚或修复有问题的发布。

5.2 功能与一致性问题

5.2.1 现象:分布式锁偶尔失效,出现数据重复处理。

  • 排查步骤
    1. 检查锁超时时间:业务逻辑执行时间是否超过了锁的租约时间(leaseTime)?查看业务方法日志,对比耗时与锁超时配置。
    2. 检查网络时钟:在分布式环境下,如果Redis服务器和客户端机器时钟不同步,可能导致锁提前被释放。检查NTP服务是否正常。
    3. 检查看门狗线程:如果使用了看门狗,检查应用是否发生了长时间GC,导致看门狗线程被挂起,无法及时续期。
    4. 检查锁释放逻辑:确保锁总是在finally块中释放,并且释放时验证了锁的value。
  • 解决方案
    • 合理设置超时:锁的超时时间应设置为“业务最大预估耗时 + 网络缓冲时间”。不要设置过长,影响故障恢复;也不要过短。
    • 确保时钟同步:所有服务器强制同步到同一NTP源。
    • 加强锁验证:确保释放锁的Lua脚本严格比对value。redis-helper应该已经做到了这一点。
    • 考虑RedLock:如果对锁的可靠性要求极高,且能接受一定的性能损失,可以考虑使用RedLock算法(需要多个独立的Redis实例),redis-helper可能也提供了实现。

5.2.2 现象:本地二级缓存与Redis数据不一致。

  • 排查步骤
    1. 确认一致性模式:当前使用的是“定时刷新”还是“发布订阅”模式?
    2. 检查刷新/订阅机制:如果是定时刷新,检查刷新间隔是否合理,刷新任务是否正常执行。如果是发布订阅,检查应用实例是否都成功订阅了频道,网络是否有分区。
    3. 检查更新入口:所有对数据的写操作(增删改),是否都同时清理了本地缓存并更新了Redis?确保更新逻辑覆盖所有代码路径。
  • 解决方案
    • 缩短刷新间隔:对于一致性要求高的数据,缩短定时刷新间隔,但这会增加Redis负载。
    • 切换到发布订阅模式:确保Redis配置支持Pub/Sub,并且应用实例的网络环境稳定。
    • 降级为仅用Redis缓存:对于强一致性要求的数据,关闭本地二级缓存,直接读Redis,牺牲一些性能换取一致性。
    • 采用最终一致性策略:为数据设置一个较短的本地缓存时间(如30秒),接受这段时间内的数据延迟,适用于大多数配置类场景。

5.3 运维与监控问题

5.3.1 如何评估和设置合理的监控阈值?

监控指标没有放之四海而皆准的阈值,需要根据业务基线来设定。

  • 缓存命中率:通常期望在90%以上。低于80%需要告警。但需注意,对于刚启动的应用或全新业务,命中率低是正常的。
  • 命令平均延迟:99线(P99)延迟应稳定在较低水平(例如,对于内存操作,P99应小于1ms)。如果P99延迟持续高于5ms或10ms,需要调查。
  • 连接数:监控连接数增长趋势。如果连接数持续缓慢增长,可能存在连接泄漏。设置一个基于历史最高值的告警(例如,超过历史峰值的120%)。
  • 内存使用率:设置一个硬性阈值(如85%)进行告警,为扩容或清理预留时间。

5.3.2 项目升级或客户端迁移注意事项

redis-helper或底层Redis客户端(如Jedis升级到Lettuce)需要升级时:

  1. 充分测试:在测试环境进行完整的集成测试和压力测试,重点关注分布式锁、管道操作、集群模式等复杂功能。
  2. 查看变更日志:仔细阅读新版本是否有不兼容的API变更、默认配置变更或已知问题。
  3. 灰度发布:在生产环境采用金丝雀发布,先在一小部分实例上部署新版本,观察监控指标(错误率、延迟、GC情况)是否正常,再逐步全量。
  4. 回滚预案:准备好一键回滚到旧版本的方案,包括配置和代码。

SKY-lv/redis-helper这类工具库的价值,在于它将Redis使用中那些“只可意会”的最佳实践和“踩坑经验”固化成了代码。它不一定能满足所有场景,但其设计思路和实现细节,为我们构建健壮、高效的缓存层提供了一个优秀的参考范本。在实际项目中,你可以直接使用它,也可以借鉴其思想,打造更适合自己团队业务特点的“Redis助手”。最终目的都是一样的:让缓存这个利器,用得更加得心应手。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/17 8:07:49

终极指南:如何用Office Custom UI Editor轻松打造专属办公界面

终极指南&#xff1a;如何用Office Custom UI Editor轻松打造专属办公界面 【免费下载链接】office-custom-ui-editor Standalone tool to edit custom UI part of Office open document file format 项目地址: https://gitcode.com/gh_mirrors/of/office-custom-ui-editor …

作者头像 李华
网站建设 2026/5/17 8:03:30

Arm Neoverse CMN-700 HN-F寄存器架构与缓存一致性配置详解

1. Arm Neoverse CMN-700 HN-F寄存器架构概述在现代SoC设计中&#xff0c;一致性互连网络&#xff08;Coherent Mesh Network&#xff09;是实现多核处理器高效协同工作的核心基础设施。作为Arm Neoverse平台的关键组件&#xff0c;CMN-700通过其独特的网格拓扑结构和分布式节点…

作者头像 李华
网站建设 2026/5/17 7:54:48

音乐数字主权革命:Unlock Music Electron桌面版完全指南

音乐数字主权革命&#xff1a;Unlock Music Electron桌面版完全指南 【免费下载链接】unlock-music-electron Unlock Music Project - Electron Edition 在Electron构建的桌面应用中解锁各种加密的音乐文件 项目地址: https://gitcode.com/gh_mirrors/un/unlock-music-electr…

作者头像 李华
网站建设 2026/5/17 7:54:48

基于RAG与知识图谱的AI论文阅读工具:从对话式理解到知识管理

1. 项目概述&#xff1a;一个AI驱动的论文阅读与知识管理工具 如果你和我一样&#xff0c;长期在AI、机器学习的前沿领域摸索&#xff0c;那你一定对“论文焦虑”深有体会。每天arXiv、ACL、NeurIPS等顶会预印本如潮水般涌来&#xff0c;每篇动辄十几页甚至几十页&#xff0c;光…

作者头像 李华
网站建设 2026/5/17 7:54:28

量子计算中的Clifford电路优化与CNOT门数最小化

1. 量子电路优化背景与挑战量子计算作为下一代计算范式&#xff0c;其核心运算单元是量子比特&#xff08;qubit&#xff09;和量子门。在NISQ&#xff08;Noisy Intermediate-Scale Quantum&#xff09;时代&#xff0c;量子硬件的噪声问题尤为突出&#xff0c;其中两比特CNOT…

作者头像 李华