*Redis CF.INSERTNX 命令
CF.INSERTNX 将一个或多个元素添加到 Cuckoo Filter 中,仅当元素之前不存在时才插入。如果过滤器不存在则自动创建。
*语法
CF.INSERTNX key [CAPACITY capacity] [NOCREATE] ITEMS item [item ...]
*参数说明
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| key | String | 是 | Cuckoo Filter 的键名 |
| CAPACITY capacity | Integer | 否 | 新过滤器的期望容量(仅在过滤器不存在时生效) |
| NOCREATE | Flag | 否 | 禁止自动创建过滤器,如果键不存在则返回错误 |
| ITEMS item... | String / Bytes | 是 | 要插入的一个或多个元素 |
*返回值
返回一个整数数组,每个元素对应一个插入操作的结果:
- 1:元素成功插入(之前不存在)
- 0:元素的指纹已存在于过滤器中(未插入)
- -1:无法插入,因为过滤器已满
特殊情况: - Simple error reply:参数数量或类型错误,或者指定了 NOCREATE 但键不存在时返回
*时间复杂度
O(n * (k + i)),其中 n 是元素数量,k 是子过滤器数量,i 是 maxIterations。
*示例
*基本用法(首次插入)
> CF.INSERTNX cf CAPACITY 1000 ITEMS item1 item2
1) (integer) 1
2) (integer) 1
*重复插入(元素已存在)
> CF.INSERTNX cf CAPACITY 1000 ITEMS item1 item2 item3
1) (integer) 0
2) (integer) 0
3) (integer) 1
*禁止自动创建
> CF.INSERTNX cf_new CAPACITY 1000 NOCREATE ITEMS item1 item2
(error) ERR not found
*批量插入并检查重复
> CF.INSERTNX cf_dedup ITEMS a b c d
1) (integer) 1
2) (integer) 1
3) (integer) 1
4) (integer) 1
> CF.INSERTNX cf_dedup ITEMS c d e f
1) (integer) 0
2) (integer) 0
3) (integer) 1
4) (integer) 1
*常见错误
| 错误 | 原因 | 解决 |
|---|---|---|
| ERR wrong number of arguments | 参数数量不足 | 检查是否提供了 ITEMS 和至少一个元素 |
| ERR not found | 指定了 NOCREATE 但键不存在 | 先使用 CF.RESERVE 创建过滤器,或移除 NOCREATE 选项 |
| ERR item exists | 键已存在但不是 Cuckoo Filter 类型 | 使用不同的键名,或删除现有键 |
*最佳实践
- 去重场景:CF.INSERTNX 适合需要去重判断的场景,例如防止重复处理任务、唯一性约束等
- 注意假阳性:由于 CF.EXISTS 可能存在假阳性(false positive),CF.INSERTNX 可能因误判元素已存在而拒绝插入。如果对假阳性敏感,建议结合其他数据结构二次确认
- 性能考虑:CF.INSERTNX 比 CF.INSERT 慢,因为每个元素插入前都需要先检查是否存在。如果不需要去重判断,优先使用 CF.INSERT
- CAPACITY 与 NOCREATE 互斥:这两个选项不能同时使用
- 批量操作:尽量一次插入多个元素,减少网络往返开销
*FAQ
Q1: CF.INSERTNX 和 CF.INSERT 有什么区别? A: CF.INSERTNX 在插入前会先检查元素是否已存在,如果存在则跳过插入并返回 0。CF.INSERT 无条件插入。CF.INSERTNX 适合去重场景,但性能稍差。
Q2: 返回 0 表示元素一定存在吗? A: 不一定。由于 Cuckoo Filter 的假阳性特性,CF.INSERTNX 可能误判元素已存在而返回 0,实际上该元素可能并未被插入过。如果需要 100% 准确的去重判断,建议配合其他数据结构(如 Redis Set)使用。
Q3: 为什么 CF.INSERTNX 比 CF.INSERT 慢? A: CF.INSERTNX 对每个元素都需要先执行 CF.EXISTS 检查(O(k + i) 复杂度),然后再决定是否插入。而 CF.INSERT 直接尝试插入。因此 CF.INSERTNX 的时间复杂度大约是 CF.INSERT 的两倍。
Q4: 如果过滤器已满,CF.INSERTNX 会返回什么? A: 会返回 -1,表示无法插入该元素。这与 CF.INSERT 的行为一致。需要注意的是,即使元素确实不存在(在另一个数据结构中确认),如果过滤器已满也无法插入。