StackExchange.Redis 系列 12:Testing 套件说明

  • 本系列博文是“伪”官方文档翻译,并非完全将官方文档进行翻译,而是我在查阅、测试原始文档并转换为自己东西后进行的“准”翻译。

  • 原始文档见此:https://stackexchange.github.io/StackExchange.Redis/

  • 本系列本博文基于 redis 5.0.6,系列中部分博文跟官方文档有出入,有不同见解 / 说明不当的地方,还请大家不吝拍砖。

StackExchange.Redis 为 windows 环境提供了测试套件,截至本文发布前,作者尚未正式发布跨平台的套件信息。

StackExchange.Redis 提供的单元和继承测试很简单,有 2 个主要步骤:

  1. 开启服务器

  2. 运行测试

  • 测试默认使用本机 Redis 服务(127.0.0.1),你可以修改 json 配置来自定义。

1
2
3
4
5
{
"RunLongRunning": true,
"MasterServer": "192.168.10.5",
"MasterPort": 2333
}

StackExchange.Redis 系列 11:Scripting 说明

  • 本系列博文是“伪”官方文档翻译,并非完全将官方文档进行翻译,而是我在查阅、测试原始文档并转换为自己东西后进行的“准”翻译。

  • 原始文档见此:https://stackexchange.github.io/StackExchange.Redis/

  • 本系列本博文基于 redis 5.0.6,系列中部分博文跟官方文档有出入,有不同见解 / 说明不当的地方,还请大家不吝拍砖。

StackExchange.Redis 库中提供了以下几个接口来让你执行 LUA 基本脚本:

  • IServer.ScriptLoad(Async)

  • IServer.ScriptExists(Async)

  • IServer.ScriptFlush(Async)

  • IDatabase.ScriptEvaluate

  • IDatabaseAsync.ScriptEvaluateAsync

要执行复杂脚本的话,可以通过 LuaScript 类来进行构建。

LuaScript 示例

StackExchange.Redis 系列 10:Profiling | 性能分析

  • 本系列博文是“伪”官方文档翻译,并非完全将官方文档进行翻译,而是我在查阅、测试原始文档并转换为自己东西后进行的“准”翻译。

  • 原始文档见此:https://stackexchange.github.io/StackExchange.Redis/

  • 本系列本博文基于 redis 5.0.6,系列中部分博文跟官方文档有出入,有不同见解 / 说明不当的地方,还请大家不吝拍砖。

StackExchange.Redis公开了一些方法和类型来启用性能分析。

性能分析接口由以下几个接口和方法组成:

  • IProfiler

  • ConnectionMultiplexer.RegisterProfiler(IProfiler)

  • ConnectionMultiplexer.BeginProfiling(object)

  • ConnectionMultiplexer.FinishProfiling(object),

  • IProfiledCommand

你可以通过 ConnectionMultiplexer 来注册一个 IProfiler 实例,无法被更改。

StackExchange.Redis 系列 9:使用 KEYS, SCAN, FLUSHDB 等命令

  • 本系列博文是“伪”官方文档翻译,并非完全将官方文档进行翻译,而是我在查阅、测试原始文档并转换为自己东西后进行的“准”翻译。

  • 原始文档见此:https://stackexchange.github.io/StackExchange.Redis/

  • 本系列本博文基于 redis 5.0.6,系列中部分博文跟官方文档有出入,有不同见解 / 说明不当的地方,还请大家不吝拍砖。

StackExchange.Redis 面向的是 redis 集群,所以需要直到哪些命令面向 database,哪些命令面向 server。
KEYS, SCAN, FLUSHDB 这些命令都属于服务端命令。

以下命令面向的是单台服务器(包含但不限于)

  • KEYS / SCAN:仅列出当前服务器上的 key;不包括更广逻辑上的 database。

  • FLUSHDB / FLUSHALL:仅移除当前服务器上的 key,不包括更广逻辑上的 database。

  • RANDOMKEY:仅随机选择当前服务器上的 key,不包括更广逻辑上的 database。

  • CLIENT

  • CLUSTER

  • CONFIG / INFO / TIME

  • SLAVEOF

  • SAVE / BGSAVE / LASTSAVE

  • SCRIPT (not to be confused with EVAL / EVALSHA)

  • SHUTDOWN

  • SLOWLOG

  • PUBSUB (not to be confused with PUBLISH / SUBSCRIBE / etc)

  • some DEBUG operations

StackExchange.Redis 系列 8:Stream 数据类型说明

  • 本系列博文是“伪”官方文档翻译,并非完全将官方文档进行翻译,而是我在查阅、测试原始文档并转换为自己东西后进行的“准”翻译。

  • 原始文档见此:https://stackexchange.github.io/StackExchange.Redis/

  • 本系列本博文基于 redis 5.0.6,系列中部分博文跟官方文档有出入,有不同见解 / 说明不当的地方,还请大家不吝拍砖。

说明

  • Stream 数据类型是在 Redis 5.0 版本新引入的。它以更抽象的方式来模拟日志数据结构。

  • 目前 StackExchange.Redis 客户端已经实现了所有原生 Stream 相关的命令。

  • 关于 Stream 的介绍可以见此

往 Streams 中写入数据

  • Stream 中的每条消息/条目都由 StreamEntry 类型表示。每个 Stream 条目包含一个唯一的 ID 和一个 Name/Value 对。

eg:通过单个 name/value对 往 Stream 中添加一条简单消息

StackExchange.Redis 系列 7:pub/sub 消息顺序

  • 本系列博文是“伪”官方文档翻译,并非完全将官方文档进行翻译,而是我在查阅、测试原始文档并转换为自己东西后进行的“准”翻译。

  • 原始文档见此:https://stackexchange.github.io/StackExchange.Redis/

  • 本系列本博文基于 redis 5.0.6,系列中部分博文跟官方文档有出入,有不同见解 / 说明不当的地方,还请大家不吝拍砖。

当你使用 pub/sub 的时候,需要考虑在一个连接中,消息是顺序处理还是并行处理。StackExchange 推荐如果可以的话是并行处理。

顺序处理的好处是你不需要要担心线程安全,且处理消息的顺序和消息的发送顺序是一致的(通过队列),但问题是消息间有可能相互延时。

1
2
3
multiplexer.GetSubscriber().SubScribe("messages", (channel, message) => {
Console.WriteLine((string)message);
});

并发处理的好处是更快,可扩展性更高,一般消息间没有什么关联的时候用并发模式。并发的问题是因为消息是无序的,你需要自己保证并发消息不会破坏你的内部状态。

1
2
3
4
var channelMessageQueue = multiplexer.GetSubscriber().SubScribe("messages");
channel.OnMessage(message =>{
Console.WriteLine((string)message.Message);
});

StackExchange.Redis 系列 6:Events 说明

  • 本系列博文是“伪”官方文档翻译,并非完全将官方文档进行翻译,而是我在查阅、测试原始文档并转换为自己东西后进行的“准”翻译。

  • 原始文档见此:https://stackexchange.github.io/StackExchange.Redis/

  • 本系列本博文基于 redis 5.0.6,系列中部分博文跟官方文档有出入,有不同见解 / 说明不当的地方,还请大家不吝拍砖。

ConnectionMultiplexer 对外提供了多个事件以便让你可以捕获内部执行情况,你可以通过这些事件按需记录日志。

事件

  • ConfigurationChanged:当 ConnectionMultiplexer 中的连接发生改变的时候该事件会被触发。

  • ConfigurationChangedBroadcast:当通过 pub/sub 接收到重新配置的消息时,该事件会被触发。通常情况下,引发该事件的是调用 IServer.MakeMaster 去改变一个节点的副本配置(该节点可以将此类请求广播到所有客户端。)

  • ConnectionFailed:任何原因导致物理连接失败的时候会触发该事件。在下次连接被重新成功建立前,该事件只会触发一次。

  • ConnectionRestored:在上一次连接失败后,连接重新被建立(恢复)的时候,会触发该事件。

  • ErrorMessage:当 Redis 服务端用错误信息响应客户端请求的时候,该事件会被触发。另外,触发该事件后,常规的异常/错误依然会返回/告知到调用方。

  • HashSlotMoved:使用“redis 集群”的时候,当 hash-slot 在节点间发生迁移的时候,该事件就会别触发。注意,请求会自动重新路由,一般用户不需要做什么特殊操作。

  • InternalError:当 StackExchange.Redis 库内部发生错误的时候会触发该事件,一般在 DEBUG 的时候可以使用该事件。

请注意,StackExchange.Redis中的 pub/sub 实现与事件类似,Subscribe / SubscribeAsync 方法接受一个 Action<RedisChannel,RedisValue> 回调,该回调在收到消息时会被触发。

StackExchange.Redis 系列 5:事务

  • 本系列博文是“伪”官方文档翻译,并非完全将官方文档进行翻译,而是我在查阅、测试原始文档并转换为自己东西后进行的“准”翻译。

  • 原始文档见此:https://stackexchange.github.io/StackExchange.Redis/

  • 本系列本博文基于 redis 5.0.6,系列中部分博文跟官方文档有出入,有不同见解 / 说明不当的地方,还请大家不吝拍砖。

Redis 中的事务说明

  • Redis 中的事务跟我们常说的数据库事务不同:

    • 数据库事务必须保证全部成功,否则就回滚。
    • 而 Redis 中的事务更偏向于“一组打包的批量执行脚本”,其中任何一条命令的执行失败,不会导致已经执行的命令回滚,也不会中断后续的命令执行。
  • 在使用数据库事务的时候,你可以在事务中使用条件判断。但在 Redis 事务中,你无法使用条件判断。(条件见下方说明)

如何使用事务?

  • 在 Redis 原生命令中使用 MULTI 来开启事务,EXEC 来执行事务(或者 DISCARD 来取消事务)

  • 一旦使用 MULTI,在 MULTI 之后的命令不会立即执行,它们会排队,直到接收到 EXEC命令。如果接收到的时 DISCARD 命令,则所有已传输的命令会全部抛弃。

    • 因为 Redis 命令会排队执行,所以无法在 Redis 中使用条件判断。

StackExchange.Redis 系列 4:Keys, Values and Channels 说明

  • 本系列博文是“伪”官方文档翻译,并非完全将官方文档进行翻译,而是我在查阅、测试原始文档并转换为自己东西后进行的“准”翻译。

  • 原始文档见此:https://stackexchange.github.io/StackExchange.Redis/

  • 本系列本博文基于 redis 5.0.6,系列中部分博文跟官方文档有出入,有不同见解 / 说明不当的地方,还请大家不吝拍砖。

Keys

  • 在 redis 的数据库中,key 是唯一的。

  • 在集群或者分片系统中,key定义了包含该数据的节点,因此 key 对于 routing commands而言相当重要。

  • 在 StackExchange.Redis 中,通过 RedisKey 这个类型来表示 keys。内部已经做好了 string 和 byte[] 类型之间的转换。并且允许你使用”字符串“作为键,或者”字节数组“作为键,如:

1
2
3
4
5
string key = ...;
db.StringIncrement(key);
//以上命令等价于
byte[] key = ...
db.StringIncrement(key);
  • StackExchange.Redis 提供了获取 key 的操作,且相当便利,如下:

StackExchange.Redis 系列 3:Pipelines and Multiplexers 说明

  • 本系列博文是“伪”官方文档翻译,并非完全将官方文档进行翻译,而是我在查阅、测试原始文档并转换为自己东西后进行的“准”翻译。

  • 原始文档见此:https://stackexchange.github.io/StackExchange.Redis/

  • 本系列本博文基于 redis 5.0.6,系列中部分博文跟官方文档有出入,有不同见解 / 说明不当的地方,还请大家不吝拍砖。

Pipeline

  • 在使用 Redis 的时候,大部分的耗时会集中在网络延时上,通过 Pipeline,可以把多次网络请求合并为 1 次,提高性能。

当你执行如下同步方法的时候:

1
2
string a = db.StringGet("a");
string b = db.StringGet("b");
  • 只有等你得到了 a 的值以后,获取 b 的值的请求才会发出去。