DiceDB SCARD 命令详解:获取集合基数(Cardinality)的完整指南
2026/9/15 10:02:05 网站建设 项目流程

DiceDB SCARD 命令详解:获取集合基数(Cardinality)的完整指南

【免费下载链接】dicedbOpen-source, low-latency key/value engine built on Valkey with query subscriptions and hierarchical storage tiers.项目地址: https://gitcode.com/GitHub_Trending/dic/dicedb

SCARD 是 DiceDB 中用于获取 Set(集合)中成员数量的命令,即返回存储在指定 key 下集合的基数(cardinality)。它是构建计数器、去重统计、在线状态追踪、实时榜单等场景中最常配合 SADD/SREM 使用的只读命令。读完本文,你将掌握 SCARD 的语法、参数与返回值、五种典型行为分支、错误处理细节,以及它在 DiceDB 源码与测试中的真实实现方式,能够直接在127.0.0.1:7379上进行验证与实战使用。

命令概述

SCARD(Set Cardinality)是 DiceDB 集合类型命令族中的核心只读命令。它的职责非常单一:返回集合中存储的成员数量

在 DiceDB 中,Set 是一种无序、成员唯一(不可重复)的集合数据结构。因此SCARD返回的数值就是该集合当前去重后的元素个数,常用于:

  • 统计去重后的活跃用户数、唯一访客数;
  • 判断集合是否为空(返回0);
  • 与 SADD / SREM 配合,动态监控集合规模变化;
  • 在实时榜单、标签系统、好友关系中快速获取集合规模。

DiceDB 的命令元数据注册在 internal/eval/commands.go,其中scardCmdMeta声明了该命令的名称(SCARD)、元信息(Returns the number of elements of the set stored at key)以及固定参数数量Arity: 2(命令名加 1 个 key 参数,即严格要求只接受一个 key)。

语法与参数

SCARD key

参数说明

参数描述类型是否必填
key要查询的集合 key,用于获取其成员数量(基数)String

命令只接受1 个key 参数,多传或少传都会触发参数数量错误(详见下文"错误处理"一节)。

命令元数据中的约束

在 internal/eval/commands.go 中,scardCmdMetaArity字段为2,表示"SCARD + 1 个参数",这与原文档"最多只能传一个 key"的约束完全一致;KeySpecsBeginIndex: 1则向框架声明该命令的第一个参数(索引 1)是 key 位置,便于命令解析与 key 定位。

返回值

条件返回值
key 存在且为 Set 类型集合中元素的数量(整数)
key 不存在0
语法错误 / key 为错误类型返回 error

返回值统一以 RESP 协议中的整数(integer)形式返回,例如(integer) 3

行为规则

当执行SCARD命令时,DiceDB 会按照以下流程处理:

  1. 检查参数数量:只允许恰好 1 个 key,否则返回参数数量错误;
  2. 检查 key 是否存在:若 key 不存在,直接返回0
  3. 检查 key 的类型:若 key 存在但不是 Set 类型(例如 String、List、Hash、Sorted Set),返回WRONGTYPE类型错误;
  4. 计算并返回基数:若 key 是合法集合,返回该集合当前成员个数。

这一行为在源码 internal/eval/store_eval.go 的evalSCARD函数中得到了一一印证:

// evalSCARD returns the number of elements of the set stored at key // Returns 0 if the key does not exist // An error response is returned if the command is used on a key that contains a non-set value(eg: string) func evalSCARD(args []string, store *dstore.Store) *EvalResponse { if len(args) != 1 { return &EvalResponse{ Result: nil, Error: diceerrors.ErrWrongArgumentCount("SCARD"), } } key := args[0] // Get the set object from the store. obj := store.Get(key) if obj == nil { return &EvalResponse{ Result: 0, Error: nil, } } // If the object exists, check if it is a set object. if err := object.AssertType(obj.Type, object.ObjTypeSet); err != nil { return &EvalResponse{ Result: nil, Error: diceerrors.ErrWrongTypeOperation, } } // Get the set object. count := len(obj.Value.(map[string]struct{})) return &EvalResponse{ Result: count, Error: nil, } }

从实现可以看出三个关键点:

  • 时间复杂度为 O(1)count := len(obj.Value.(map[string]struct{}))直接对 Go 的 map 取长度,不遍历成员,因此无论集合多大,SCARD都能常数时间内返回结果;
  • 底层数据结构:DiceDB 的 Set 在内部使用map[string]struct{}表示(internal/eval/store_eval.go),struct{}空结构体不占额外内存,同时天然保证了成员唯一性——这正是集合"成员不重复"特性的底层来源;
  • 类型判定object.AssertType配合object.ObjTypeSet(定义于 internal/object/object.go)完成类型检查,错误路径统一返回diceerrors.ErrWrongTypeOperation

错误处理

1. 类型错误(Wrong Type of Key)

  • 错误信息(error) ERROR WRONGTYPE Operation against a key holding the wrong kind of value
  • 触发条件:key 存在,但关联的不是 Set 类型,而是 String、List、Hash 或 Sorted Set 等其他数据类型。DiceDB 期望 key 必须关联集合类型。
  • 源码依据:internal/eval/store_eval.go 中object.AssertType(obj.Type, object.ObjTypeSet)失败后返回diceerrors.ErrWrongTypeOperation;该错误消息定义在 internal/errors/errors.go。

2. 参数数量错误(Wrong Number of Arguments)

  • 错误信息(error) ERROR wrong number of arguments for 'scard' command
  • 触发条件:传入了 0 个 key 或 2 个及以上 key。
  • 源码依据:internal/eval/store_eval.go 中len(args) != 1时返回diceerrors.ErrWrongArgumentCount("SCARD");该错误由 internal/errors/errors.go 的工厂函数生成。

示例

以下示例全部基于 DiceDB 默认端口127.0.0.1:7379

基础示例

向集合myset依次添加三个成员,再用SCARD获取集合基数:

127.0.0.1:7379> SADD myset "apple" (integer) 1 127.0.0.1:7379> SADD myset "banana" (integer) 1 127.0.0.1:7379> SADD myset "cherry" (integer) 1 127.0.0.1:7379> SCARD myset (integer) 3

集合去重特性对 SCARD 的影响

由于 Set 保证成员唯一,重复添加相同成员不会增加基数。利用这一特性,SCARD天然成为"去重计数"工具:

127.0.0.1:7379> SADD tag:users "alice" (integer) 1 127.0.0.1:7379> SADD tag:users "alice" (integer) 0 127.0.0.1:7379> SADD tag:users "bob" (integer) 1 127.0.0.1:7379> SCARD tag:users (integer) 2

第二次SADD返回0说明成员已存在未新增,因此SCARD仍为2而非3

不存在的 key

查询一个从未创建过的 key,返回0(DiceDB 不报错,直接视为空集合):

127.0.0.1:7379> SCARD nonexistingset (integer) 0

错误示例:类型错误

对存储字符串值的 key 执行SCARD

127.0.0.1:7379> SET mystring "hello" OK 127.0.0.1:7379> SCARD mystring (error) ERROR WRONGTYPE Operation against a key holding the wrong kind of value

错误示例:参数数量错误

不传参数或传入多个参数:

127.0.0.1:7379> SCARD (error) ERROR wrong number of arguments for 'scard' command 127.0.0.1:7379> SCARD myset1 myset2 (error) ERROR wrong number of arguments for 'scard' command

源码与测试验证

SCARD 的实现位于 internal/eval/store_eval.go,命令注册位于 internal/eval/commands.go。

在单元测试 internal/eval/eval_test.go 的testEvalSCARD中,覆盖了五类关键场景,与本文所述行为一一对应:

测试用例输入预期结果
SCARD with wrong number of arguments["mykey", "value"]ErrWrongArgumentCount("SCARD")
SCARD on key with invalid typeSET mykey value,再SCARD mykeyErrWrongTypeOperation
SCARD with non existing keySCARD mykey(key 不存在)0,无错误
SCARD with existing key and no memberSADD mykey(空添加)再 SCARD0,无错误
SCARD with existing keySADD mykey a b再 SCARD2,无错误

这些测试通过runMigratedEvalTests驱动evalSCARD执行,完整覆盖了"参数错误、类型错误、空集合、非空集合"全部行为分支,可作为理解命令语义与回归验证的直接依据。

使用建议与注意事项

  • 用 SCARD 而非 LLEN/HLEN 判断集合规模:SCARD 只适用于 Set 类型,若 key 被误存为其他类型会报WRONGTYPE错误,业务代码中应先通过TYPE命令确认 key 类型,或使用 try/catch 捕获类型错误;
  • 空集合与不存在 key 等价:两者都返回0,因此无法仅凭SCARD区分"key 不存在"与"key 存在但为空集",如业务需要区分,可结合EXISTS命令判断;
  • 频繁调用成本极低:由于底层是 map 长度取值,SCARD是 O(1) 操作,即使在高频监控集合大小的场景下也无需担心性能开销;
  • 注意命令名称大小写:DiceDB 命令名大小写不敏感,SCARDscardScard均可正常执行,但参数数量必须严格为一个 key。

通过本文的语法说明、行为规则、错误处理与源码佐证,你已经可以放心地在项目中用SCARD完成集合基数的查询与监控,并能够根据报错信息快速定位数据类型或参数层面的问题。

【免费下载链接】dicedbOpen-source, low-latency key/value engine built on Valkey with query subscriptions and hierarchical storage tiers.项目地址: https://gitcode.com/GitHub_Trending/dic/dicedb

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询