Bitmap 很容易给人一种「按位存储,所以一定省内存」的感觉。这个判断只说对了一半:当 offset 连续且密集时它很省;当 offset 稀疏且巨大时,它会直接按最大 offset 扩容。
SETBIT key 100000000 1 不会只存一个 1,而是要让底层 String 扩到能覆盖这个位置。Redis 还会把中间字节清零,这就是某些线上事故里一条命令吃掉十几 MB 的原因。
先把机制边界说清楚
这一篇讨论 Bitmap 和 Bitfield 的内存模型,不讨论所有统计系统。Bitmap 适合布尔标记和密集 ID,不适合把雪花 ID、手机号这类大跨度值直接当 offset。
整体路径
上面这张图先把主线铺开:最大 offset 决定 SDS 至少要扩到哪里。读 Redis 这类系统,最重要的是别只停在命令接口,要继续追问它在内存里是什么形状、在主线程上走多远、失败时会留下什么状态。
底层机制
- Bitmap 没有独立底层类型,所有位都落在 String 的 SDS 字节数组里。
- offset 会换算成字节位置,超过当前长度时触发扩容并填零。
BITCOUNT、BITOP会按字节范围扫描,范围越大,CPU 成本越高。- Bitfield 在同一个 String 上维护多个定长计数器,原子性好,但溢出策略要提前设计。
这些机制放在一起看,就能把「这个命令能不能用」改成「这个命令在当前数据规模下还便不便宜」。Redis 的很多坑,不是命令本身错了,而是数据规模和访问方式已经越过了它的舒适区。
取舍与边界
Bitmap 的收益来自密度。你把连续用户序号映射成 offset,它很香;你把稀疏业务 ID 直接扔进去,它会很贵。
典型问题:用机制化例子排查
- 上线前估算最大 offset,而不是只估算置 1 的数量。
- 对稀疏 ID 做连续映射或分桶,例如按日期、业务线拆 key。
- 用
STRLEN和MEMORY USAGE看真实占用,不要只看 bit 数。 - 大范围
BITOP放到离线任务或低峰期,避免阻塞在线请求。
收束:一句判断
Bitmap 省的是密集布尔集合,不是任意稀疏空间。
关于十三Tech
我是十三,All in AI Agent 方向的架构师,专注 AI 工程实践。
我相信 AI 是程序员的最佳搭档,也希望帮助每一位开发者更好地驾驭 AI。
如果你想继续跟完这套「图解 Redis」,欢迎关注公众号 「十三Tech」。后续会继续按数据结构、底层机制、持久化、高可用和实战排查这条线更新。

