Keys, Values and Channels

在 redis,keys 与其他有很大的区别。key 是数据库中数据的唯一标识(可以是 String,List,Hash 或任何其他 redis 数据类型)。此外,在处理集群或分片系统时,关键是定义包含此数据的节点(如果有副本,则为节点),因此,这些 key 对于路由命令至关重要。

与 values 形成对比。value 是针对 key 存储的东西:单独(针对 String 数据)或成组存储。value 不影响命令路由(注意:当指定 BY 或 GET 时,SORT 命令除外)。同样,出于操作目的,value 通常由 redis 解释:

  • incr 命令把 string 当作 numeric
  • 排序支持数字或 unicode 规则。
  • 更多

关键是 API 需要了解什么是 key 和什么是 value。这反映在 StackExchange.Redis API 中,但好消息是,大多数时候你根本不需要了解这一点。

使用 pub/sub 时,我们正在处理 channels;channels 不影响路由(因此它们不是键),但是与常规 values 完全不同,因此应单独考虑。

Keys

StackExchange.Redis 通过 RedisKey 类型表示 keys。它可以与 stringbyte[] 进行隐式转换,从而允许使用文本 key 和二进制 key 而不会造成任何复杂性。 例如,StringIncrement 方法将 RedisKey 作为第一个参数:

string key = ...
db.StringIncrement(key);

或者

byte[] key = ...
db.StringIncrement(key);

同样,有些操作会将 keys 作为 RedisKey 返回:

string someKey = db.KeyRandom();

Values

StackExchange.Redis 通过 RedisValue 类型表示 values。与 RedisKey 一样,存在隐式转换,例如:

db.StringSet("mykey", "myvalue");

但是,除了文本和二进制内容外,value 还可能需要表示类型化的原始数据:最常见的(以.NET术语)Int32Int64DoubleBoolean。 因此,与 RedisKey 相比,RedisValue 提供了更多的转换支持:

db.StringSet("mykey", 123); // this is still a RedisKey and RedisValue
...
int i = (int)db.StringGet("mykey");

请注意,虽然从 value 到 RedisValue 的转换是隐式的,但从 RedisValue 到 value 的许多转换都是显式的:这是因为如果数据没有适当的值,这些转换很可能会失败。

另外需要注意的是,在进行数字处理时,redis 将不存在的 key 视为零; 为了与此保持一致,将 nil 响应视为 0:

db.KeyDelete("abc");
int i = (int)db.StringGet("abc"); // this is ZERO

如果您需要检测nil条件,则可以进行检查:

db.KeyDelete("abc");
var value = db.StringGet("abc");
bool isNil = value.IsNull; // this is true

或更简单地说,只需使用提供的 Nullable<T> 支持:

db.KeyDelete("abc");
var value = (int?)db.StringGet("abc"); // behaves as you would expect

Hashes

由于 hashes 中的字段名称不会影响命令路由,因此它们不是 keys,而是可以同时使用文本名称和二进制名称。 因此,就 API 而言,它们被视为 values。

Channels

发布/订阅的 channel 名称由 RedisChannel 类型表示; 这在很大程度上与 RedisKey 相同,但是是独立处理的,因为尽管 channel name 是一级元素,但它们不会影响命令路由。

Scripting

Redis中的Lua脚本具有两个显着特征:

  • 输入必须将 keys 和 values 分开(脚本内的键和值分别为 KEYS 和 ARGV)
  • 返回格式没有预先定义:取决于你的脚本

因此,ScriptEvaluate 方法接受两个单独的输入数组:一个用于 keys 的 RedisKey[],一个用于 values 的 RedisValue[](两者都是可选的,并且如果省略则假定为空)。这可能是你实际上需要在代码中输入 RedisKeyRedisValue 的少数几次之一,这仅仅是由于数组差异规则所致:

var result = db.ScriptEvaluate(TransferScript,
    new RedisKey[] { from, to }, new RedisValue[] { quantity });

(其中 TransferScript 是一些包含Lua的字符串,此示例未显示)

响应使用 RedisResult 类型(这是脚本编写所独有的;通常,API 会尝试尽可能直接和清晰地表示响应)。和以前一样,RedisResult 提供了一系列转换操作:实际上比 RedisValue 更多,因为除了被解释为文本,二进制,基元和可为空的基元之外,响应还可以解释为此类的数组,例如:

string[] items = db.ScriptEvaluate(...);

总结

在 API 中使用的类型经过精心选择,以区分 redis keys 和 values。在大多数情况下,提供自动转换操作。


译文地址: https://www.cnblogs.com/liang24/p/13847107.html