如何利用Redis位运算实现高并发下的状态机方案_通过BITOP进行逻辑运算

梦明酱_6260

梦明酱_6260

2026-06-09

165人浏览

原创

bitop适合状态交并差但非状态机引擎,仅执行原子位运算(and/or/xor/not)输出新位图;状态流转需setbit+客户端逻辑+bitop聚合配合,不可单靠bitop实现条件迁移或过程校验。

如何利用redis位运算实现高并发下的状态机方案_通过bitop进行逻辑运算

BITOP 适合做状态交并差,但别直接拿它当状态机引擎

BITOP 不是状态机的替代品,它只负责对多个位图做原子级逻辑运算(AND/OR/XOR/NOT),输出新位图。真要实现「状态流转」,得靠 SETBIT + 客户端逻辑控制 + BITOP 聚合三者配合。比如用户权限变更、设备在线/离线/故障三态标记,不能只靠一次 BITOP OR 就完成状态迁移——它不记录变化过程,也不校验前置条件。

常见错误现象:BITOP AND user:status:final user:online user:authed user:paid 执行后发现结果为空,不是逻辑错了,而是三个源 key 中任意一个在某 bit 位为 0,结果就为 0;而你真正想表达的可能是「只要满足任意两个条件就允许访问」,这已经超出 BITOP 单次运算能力范围。

  • BITOP 的每个操作都是无状态的:输入确定,输出确定,不保留中间状态或上下文
  • AND/OR/XOR 要求所有参与 key 的 bit 偏移对齐才有意义;若 user:online 最大 offset 是 1000,user:authed 是 5000000,则 AND 结果长度取 5000000/8 字节,前 1000 位之外全是 0,容易误判
  • NOT 只支持单 key,且会按该 key 当前最大偏移补零,可能导致高位稀疏时内存暴涨

用 BITOP 实现「多条件组合状态」的正确姿势

把不同维度的状态拆成独立位图,再用 BITOP 组装出复合判定结果,比在单个 key 里用多 bit 编码状态更清晰、更易维护。例如设备管理场景:

  • device:online:{date}:第 i 位 = 1 表示设备 i 当日在线
  • device:alarm:{date}:第 i 位 = 1 表示设备 i 当日触发告警
  • device:maintained:{date}:第 i 位 = 1 表示设备 i 当日被人工维护过

要统计「当日在线且未告警」的设备数,执行:

BITOP AND device:healthy:20260527 device:online:20260527 device:alarm:20260527
BITCOUNT device:healthy:20260527

注意:device:alarm:20260527 里存的是「告警发生」,所以先用 BITOP NOT 取反再 AND 更合理:

Redis Skill - 高性能缓存管理
Redis Skill - 高性能缓存管理

Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。

下载
BITOP NOT device:healthy:20260527 device:alarm:20260527
BITOP AND device:healthy:20260527 device:online:20260527 device:healthy:20260527

这样避免了手动构造全 1 位图的麻烦,也规避了 NOT 对高位稀疏 key 的风险(只要 device:alarm:20260527 本身不稀疏就行)。

BITOP 在高并发下卡住的真实原因和绕过方法

BITOP 卡住不是因为并发量大,而是因为某个参与运算的 key 实际只设置了极少数高位 bit(比如 SETBIT user:flag 99999999 1),导致 Redis 必须分配约 12.5MB 内存(99999999 ÷ 8 ÷ 1024 ÷ 1024)来加载从 0 到该 offset 的完整字节数组——哪怕其他 99.99% 的字节都是 0。

实测:10 个 100MB 的密集 bitmap 做 BITOP OR,耗时约 300ms;但混入一个只设了第 1 亿 bit 的 key,峰值内存飙升至 12GB,超时失败。

  • 检查高位稀疏 key:STRLEN key 返回字节数,乘以 8 就是当前有效 bit 上限;若远小于业务预期最大 offset,说明有稀疏写入
  • 禁止人工用 SETBIT 写超大 offset;用户 ID 映射到 bit 位必须做哈希或取模压缩(如 user_id % 10000000
  • 替代方案:不用 BITOP 全量计算,改用 BITPOS key 1 start end 分段扫描各 key 的置 1 位置,客户端求交集。内存恒定,但网络请求变多,适合对延迟不敏感、对 OOM 零容忍的场景

为什么 BITOP 后还要配 BITCOUNT 或 BITPOS?

BITOP 只产生新位图,不返回任何统计信息。你无法知道 BITOP AND dest k1 k2 后 dest 里到底有多少个 1,必须显式调用 BITCOUNT dest。同理,若只想知道第一个满足「在线且已认证」的用户 ID,得用 BITPOS dest 1,而不是假设 BITOP 自带定位能力。

容易被忽略的关键点:

  • BITCOUNT 默认按字节统计,若你用 unit: 'BIT' 指定了位范围,务必确认 startend 是位偏移而非字节偏移,否则结果错位
  • BITPOSvalue 1 返回首个 1 的位置,查 value 0 返回首个 0 的位置;但若整个范围全是 1,它返回 -1 —— 这不是错误,是设计如此,需在代码里处理
  • BITOP 的 destkey 若已存在,会被覆盖;若希望保留历史结果,得用唯一命名(如加时间戳或 hash),否则并发写可能互相擦除

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

redis

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

3989

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

3495

11

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

6152

6

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

583

6

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

696

6

mysql和redis怎么保证双写一致性
mysql和redis怎么保证双写一致性

确保 mysql 和 redis 双写一致性的技术包括:1、事务性更新:同时更新 mysql 和 redis,保证一致性;2、主从复制:mysql 主服务器更改同步到 redis 从服务器;3、基于事件的更新:mysql 记录更改并发送到 redis等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

5542

6

redis缓存一般存些什么数据
redis缓存一般存些什么数据

redis缓存中存储的数据类型包括:字符串、哈希、列表、集合、有序集合、位图、地理空间数据和hyperloglog。这些数据类型适用于存储各种数据,从简单信息到复杂对象和地理位置。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

1120

6

redis的8种数据类型有哪些
redis的8种数据类型有哪些

redis 提供 8 种数据类型:字符串(文本、数字、二进制)、哈希(键值对)、列表(有序集合)、集合(无序唯一元素)、有序集合(按分数排序)、地理空间(地理位置)、hyperloglog(估计大数据基数)和位图(位序列存储)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

916

6

redis主要作用有哪些
redis主要作用有哪些

redis 的主要作用包括:1. 缓存数据,提高访问速度;2. 充当消息队列,实现消息传递;3. 存储各种数据类型,如字符串、散列和集合;4. 管理会话信息,确保可靠性和可用性;5. 限制请求速率,防止服务器超载等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

5038

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.5万人学习