【StackExchange.Redis笔记】基础
连接对象ConnectionMultiplexer
ConnectionMultiplexer
是StackExchange.Redis
的核心对象,ConnectionMultiplexer
应被多个调用之间共享使用。不需要为每个操作创建一个 ConnectionMultiplexer
,它是完全线程安全的。可以通过使用 ConnectionMultiplexer.Connect
或 ConnectionMultiplexer.ConnectAsync
创建连接对象,并传入配置字符串或 ConfigurationOptions
对象。 配置字符串可以采用一系列逗号分隔的节点的形式:
创建连接:
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("server1:6379,password=123456");
有了ConnectionMultiplexer
之后,你可能需要做以下三件事:
- 访问 redis 数据库(使用集群时,单个逻辑数据库可能分布在多个节点上)
- 使用 redis 的发布/订阅功能
- 访问单独服务器以进行维护/监视
使用redis数据库
IDatabase db = redis.GetDatabase();
从GetDatabase
返回的对象是一个成本很低的通道对象,不需要存储。redis 支持多个数据库,可以在GetDatabase
的参数中指定,默认是0。
得到IDatabase
后,就可以使用 redis API。 请注意,所有方法都具有同步和异步实现。
最简单的操作是存储和检索值:
string value = "abcdefg";
db.StringSet("mykey", value);
...
string value = db.StringGet("mykey");
Console.WriteLine(value); // writes: "abcdefg"
发布订阅
redis 的另一个常见用法是作为 发布/订阅消息分发工具。
并且在连接失败的情况下,ConnectionMultiplexer
将处理重新订阅所请求的信道的所有细节。
ISubscriber sub = redis.GetSubscriber();
同样,从 GetSubscriber
返回的对象是一个不需要存储的低成本的通道对象。
发布/订阅 API 没有数据库的概念。所有订阅都是全局的:它们不限于 ISubscriber
实例的生命周期。
redis 中的发布/订阅功能使用命名的 “channels” ;channels 不需要事先在服务器上定义
如在.NET中常见的,订阅采用回调委托的形式,它接受通道名称和消息:
sub.Subscribe("messages", (channel, message) => {
Console.WriteLine((string)message);
});
访问单个服务器
出于维护目的,有时有必要发出服务器特定的命令:
IServer server = redis.GetServer("localhost", 6379);
GetServer
方法将接受一个 EndPoint
或唯一标识服务器的名称/值对。 从 GetServer
返回的对象是成本很低的通道对象,不需要存储,并且可以选择指定异步状态。请注意,可用 endpoints
也可用:
EndPoint[] endpoints = redis.GetEndPoints();
在 IServer 实例中,可以使用 Server 命令。 例如:
DateTime lastSave = server.LastSave();
ClientInfo[] clients = server.ClientList();
配置
基本配置字符串
最简单的 配置示例只需要一个主机名:
var conn = ConnectionMultiplexer.Connect("localhost");
这将使用默认的redis端口(6379)连接到本地计算机上的单个服务器。 附加选项只是简单地附加(逗号分隔)。 端口通常用冒号(:)表示。 配置选项在名称后面包含一个=。 例如:
var conn = ConnectionMultiplexer.Connect("redis0:6380,redis1:6380,allowAdmin=true");
下面显示了 string 和 ConfigurationOptions 表示之间的映射概述,但您可以轻松地在它们之间切换:
ConfigurationOptions options = ConfigurationOptions.Parse(configString);
或者:
string configString = options.ToString();
常见的用法是将 基础配置 细节存储在一个字符串中,然后在运行时应用特定的详细信息:
string configString = GetRedisConfiguration();
var options = ConfigurationOptions.Parse(configString);
options.ClientName = GetAppName(); // only known at runtime
options.AllowAdmin = true;
conn = ConnectionMultiplexer.Connect(options);
带密码的 Microsoft Azure Redis 示例
var conn = ConnectionMultiplexer.Connect("contoso5.redis.cache.windows.net,ssl=true,password=...");
配置选项
配置字符串 | ConfigurationOptions | 默认值 | 含义 |
---|---|---|---|
abortConnect=bool | AbortOnConnectFail | true (Azure 上默认值为 false) | 如果为true,Connect 没有服务器可用时将不会创建连接 |
allowAdmin=bool | AllowAdmin | false | 启用被认为具有风险的一系列命令 |
channelPrefix=string | ChannelPrefix | null | 所有发布/订阅操作的可选频道前缀 |
connectRetry=int | ConnectRetry | 3 | 在初始 Connect 期间重复连接尝试的次数 |
connectTimeout=int | ConnectTimeout | 5000 | 连接操作的超时时间(ms) |
configChannel=string | ConfigurationChannel | __Booksleeve_MasterChanged | 用于传达配置更改的广播通道名称 |
configCheckSeconds=int | ConfigCheckSeconds | 60 | 检查配置的时间(秒)。如果支持的话,这会以交互式套接字的方式保持活动。 |
defaultDatabase=int | DefaultDatabase | null | 默认数据库索引, 从 0 到 databases - 1(0 到 Databases.Count -1) |
keepAlive=int | KeepAlive | -1 | 发送消息以帮助保持套接字活动的时间(秒)(默认时间60s) |
name=string | ClientName | null | 标识 redis 中的连接 |
password=string | Password | null | redis 服务器的密码 |
proxy=proxy type | Proxy | Proxy.None | 正在使用的代理类型(如果有); 例如“twemproxy” |
resolveDns=bool | ResolveDns | false | 指定DNS解析应该是显式和热切,而不是隐式 |
responseTimeout=int | ResponseTimeout | SyncTimeout | socket 健康检查的响应时间(ms,毫秒) |
serviceName=string | ServiceName | null | 目前尚未实施(预期与sentinel一起使用) |
ssl=bool | Ssl | false | 指定应使用SSL加密 |
sslHost=string | SslHost | null | 在服务器证书上强制执行特定的SSL主机标识 |
syncTimeout=int | SyncTimeout | 1000 | 允许同步操作的时间(ms) |
tiebreaker=string | TieBreaker | __Booksleeve_TieBreak | 用于在不明确的主场景中选择服务器的键 |
version=string | DefaultVersion | (3.0 in Azure, else 2.0) | Redis版本级别(当服务器要使用的版本默认不可用时使用) |
writeBuffer=int | WriteBuffer | 4096 | 输出缓冲区的大小 |
ReconnectRetryPolicy=IReconnectRetryPolicy | ReconnectRetryPolicy | 重新连接重试策略 |
禁用命令
在许多常见的情况下,StackExchange.Redis将自动配置很多设置,包括服务器类型和版本,连接超时和主/从关系。 有时,在redis服务器上禁用了这些命令。 在这种情况下,可以提供更多的信息:
ConfigurationOptions config = new ConfigurationOptions
{
EndPoints =
{
{ "redis0", 6379 },
{ "redis1", 6380 }
},
CommandMap = CommandMap.Create(new HashSet<string>
{ // EXCLUDE a few commands
"INFO", "CONFIG", "CLUSTER",
"PING", "ECHO", "CLIENT"
}, available: false)
};
它相当于命令字符串:
redis0:6379,redis1:6380,$CLIENT=,$CLUSTER=,$CONFIG=,$ECHO=,$INFO=,$PING=
重命名命令
redis的一个很不寻常的功能是可以禁用或重命名或禁用并重命名单个命令。
根据前面的例子,这是通过CommandMap来实现的,但不是传递一个HashSet
“null”或空白值记录命令被禁用。 例如:
var commands = new Dictionary<string,string> {
{ "info", null }, // disabled
{ "select", "use" }, // renamed to SQL equivalent for some reason
};
var options = new ConfigurationOptions {
// ...
CommandMap = CommandMap.Create(commands),
// ...
}
以上代码等同于(在连接字符串中):
$INFO=,$SELECT=use
事件
- ConnectionMultiplexer 类型提供了许多事件可以用来理解被封装的底层是怎么工作的。这在记录日志时会特别有用。
- ConfigurationChanged - 当连接的配置从 ConnectionMultiplexer 内部发生修改时触发
- ConfigurationChangedBroadcast - 当经由发布/订阅接收到重新配置消息时引发; 这通常是由于 IServer.MakeMaster 用于更改节点的复制配置,可以选择将这样的请求广播到所有客户端
- ConnectionFailed - 当连接由于无论任何原因失败时触发; 请注意,在连接重新建立之前是不会再收到该连接的 ConnectionFailed 通知
- ConnectionRestored - 当重新建立到先前失败的节点的连接时触发
- ErrorMessage - 当redis服务器响应任何用户发起的具有错误消息的请求时触发; 这种情况不包含将被报告给直接调用者的常规异常/故障的情况
- HashSlotMoved - 当“redis集群”指出 散列槽(hash-slot) 已在节点之间迁移时触发; 请注意,请求通常会自动重新路由,因此用户不需要在这里做任何特殊操作
- InternalError - 当库在一些意想不到的方式失败时触发; 这主要是为了调试目的,并且大多数用户应该不需要这个事件
需要注意,StackExchange.Redis 中的 发布/订阅 工作方式与事件非常相似,接收到消息时会调用接受一个 Action<RedisChannel, RedisValue> 类型回调方法的 Subscribe / SubscribeAsync 方法。
CommandFlags
CommandFlags 是 StackExchange.Redis 库中的一个枚举类型,用于指定 Redis 命令的标志位,控制命令的执行方式和行为。下面是 CommandFlags 枚举的所有项:
- None:默认值,表示没有指定任何标志位。
- DemandMaster:要求命令只在主节点上执行,如果当前连接的节点是从节点,则会引发异常。
- PreferMaster:优先在主节点上执行命令,如果当前连接的节点是从节点,则会将命令发送给主节点并等待结果。
- HighPriority:将命令标记为高优先级,在 Redis 服务器上可能会得到更快的处理。
- FireAndForget:以“发出并忘记”的方式执行命令,即命令被发送给 Redis 服务器后,客户端不会等待命令的执行结果,而是立即返回。
- NoRedirect:禁止命令重定向,即如果命令需要在从节点上执行,而当前连接的节点是主节点,则会引发异常。
- NoScriptCache:禁用脚本缓存,即如果命令是 Lua 脚本,则不会使用脚本缓存。
- NoPipeline:禁用管道,即命令不会被添加到管道中批量执行。
- NoConnect:禁用自动连接,即如果连接断开,命令不会自动重新连接。
- AllowReplica:允许在从节点上执行命令。
- HighPriorityExpiry:将命令标记为高优先级并设置过期时间,在 Redis 服务器上可能会得到更快的处理。
这些标志位可以根据需要进行组合使用,以控制命令的执行方式和行为。