Redis
这页对应 3.x 里的 Redis 使用方式,核心组件是 Redis 缓存(Aegis.Caching.Redis)。其他和 Redis 相关的能力,如 Redis 会话、Redis ID 容器、Redis 事件总线,都是建立在这层基础能力之上的。
先记住 Redis 的边界
当前 Redis 体系主要分成两层:
Aegis.Caching.Redis负责 Redis 数据源、脚本管理和基础访问- 其他扩展组件在这层之上实现认证会话、ID 容器或事件容器
所以 Redis 接入的第一步通常不是改 Component.deps.json,而是:
- 准备
Redis配置 - 定义
RedisSource - 在服务注册阶段执行
AddRedisSource<T>()
最小接入方式
1. 准备 Redis 配置
{
"Redis": {
"RedisMode": "Standalone",
"ConnectionString": "127.0.0.1:6379,defaultDatabase=2",
"SentinelString": "",
"IsRWSplitting": true,
"ScriptPath": ""
}
}
2. 定义自己的 RedisSource
public class AegisRedisSource : RedisSourceBase
{
public AegisRedisSource(RedisOptions redisOptions) : base(redisOptions)
{
}
}
3. 在服务注册阶段注入
services.AddRedisSource<AegisRedisSource>(
ConfigManager.Get<RedisOptions>("Redis"));
4. 在业务类中直接注入
public class UserService : IUserContract
{
private readonly AegisRedisSource _redis;
public UserService(AegisRedisSource redis)
{
_redis = redis;
}
}
四种最常见的模式怎么配
单实例
{
"Redis": {
"RedisMode": "Standalone",
"ConnectionString": "127.0.0.1:6379,defaultDatabase=2",
"SentinelString": "",
"IsRWSplitting": false,
"ScriptPath": ""
}
}
主从
{
"Redis": {
"RedisMode": "MasterSlave",
"ConnectionString": "10.0.0.11:6379;10.0.0.12:6379,defaultDatabase=2",
"SentinelString": "",
"IsRWSplitting": true,
"ScriptPath": ""
}
}
哨兵
{
"Redis": {
"RedisMode": "Sentinel",
"ConnectionString": "10.0.0.11:26379;10.0.0.12:26379;10.0.0.13:26379",
"SentinelString": "mymaster,defaultDatabase=2",
"IsRWSplitting": true,
"ScriptPath": "{CurrentDirectory}/Scripts/"
}
}
集群
{
"Redis": {
"RedisMode": "Cluster",
"ConnectionString": "10.0.0.21:6379;10.0.0.22:6379;10.0.0.23:6379",
"SentinelString": "",
"IsRWSplitting": false,
"ScriptPath": ""
}
}
常见配置项怎么理解
| 配置项 | 作用 |
|---|---|
RedisMode | 指定 Redis 拓扑模式 |
ConnectionString | 主连接串,单节点或多节点地址写在这里 |
SentinelString | 哨兵模式下的补充参数 |
IsRWSplitting | 是否读写分离 |
ScriptPath | 启动时统一加载脚本的目录 |
如果你们后面还要做多级缓存或降级保护,还会继续用到:
| 配置项 | 作用 |
|---|---|
Resilience.Score | 降级前分值上限 |
Resilience.RecoverScore | 恢复所需分值 |
Resilience.HeartBeatInterval | 心跳间隔 |
Resilience.FallbackPolicy | 出故障时是降级还是直接抛错 |
L1Cache.Enabled | 是否开启本地一级缓存 |
RedisSource 最常见的几类操作
读写普通对象
await _redis.SetAsync("user:1001", user, 300);
var user = await _redis.GetAsync<UserDto>("user:1001");
await _redis.DelAsync("user:1001");
操作集合
await _redis.SAddAsync("role:admin", "1001");
await _redis.SRemAsync("role:admin", "1001");
var diff = await _redis.SDiffAsync("role:admin", "role:guest");
操作哈希字段
await _redis.HSetAsync("doctor:1001", "name", "张三");
var doctorName = await _redis.HGetAsync<string>("doctor:1001", "name");
var hasName = await _redis.HExistsAsync("doctor:1001", "name");
脚本管理怎么接
如果项目里有 Lua 脚本,最省心的做法是统一放到一个目录,让 RedisSource 启动时自动加载。
配置脚本目录
{
"Redis": {
"ScriptPath": "{CurrentDirectory}/Scripts/"
}
}
手动追加脚本
_redis.Scripts.AddScript("GetBiLocker", luaContent);
追加脚本文件
_redis.Scripts.AddScriptByPath("C:\\Scripts\\GetBiLocker.lua");
执行脚本
var result = _redis.Scripts.ExecuteScript(
"GetBiLocker",
"lock:key",
new object[] { "inputKey", 30 });
BiLocker 怎么用
Redis 里当前还提供了一组双边锁能力,常见用途是把一对互斥关系写到同一个主键空间下,例如床位双向占用、左右映射关系、成对绑定关系等。
先准备脚本目录
BiLocker 依赖 Redis 脚本,所以要先保证脚本目录已经被 RedisSource 正常加载。
{
"Redis": {
"ScriptPath": "{CurrentDirectory}/Scripts/"
}
}
设置双边锁
var isLocked = await _redis.Scripts.SetBiLock(
"BedLock",
key1,
key2,
timeout: 30,
isForce: false,
side: BiLockSide.Left);
检查某一侧是否已经被锁定
var isLocked = await _redis.Scripts.CheckBiLock(
"BedLock",
key1,
BiLockSide.Left);
释放双边锁
var removed = await _redis.Scripts.RemoveBiLock(
"BedLock",
key1,
BiLockSide.Left);
刷新双边锁过期时间
var refreshed = await _redis.Scripts.RefreshBiLock(
"BedLock",
leftKey: "A",
rightKey: "B",
delaySeconds: 30);
BiLockSide 表示什么
| 枚举值 | 说明 |
|---|---|
BiLockSide.Left | 以左侧身份参与当前锁关系 |
BiLockSide.Right | 以右侧身份参与当前锁关系 |
什么时候适合用 isForce
isForce = false 更适合正常业务锁定。
只有你已经确认需要强制覆盖旧锁关系时,再考虑设为 true。
一个项目接多个 Redis 怎么办
不要在一个 RedisSource 里硬塞多个配置。
更稳的做法是给不同用途定义不同的 RedisSource。
public class BizRedisSource : RedisSourceBase
{
public BizRedisSource(RedisOptions redisOptions) : base(redisOptions)
{
}
}
public class SessionRedisSource : RedisSourceBase
{
public SessionRedisSource(RedisOptions redisOptions) : base(redisOptions)
{
}
}
然后分别绑定:
services.AddRedisSource<BizRedisSource>(
ConfigManager.Get<RedisOptions>("BizRedis"));
services.AddRedisSource<SessionRedisSource>(
ConfigManager.Get<RedisOptions>("SessionRedis"));
什么时候要继续看其他 Redis 相关文档
要把登录态放到 Redis
看 Redis 用户会话(Aegis.Authorization.RedisUserManager)。
要给 ID 生成器加 Redis 容器
看 ID生成器 和 Aegis.IdGenerator.Provider.Redis。
要给事件总线加 Redis 容器
看 Aegis.EventBus.Container.Redis。
要给业务加多级缓存
看 多级缓存。
常见问题
为什么配置写了,但容器里还是拿不到 RedisSource
因为 Redis 不是自动装配组件。
只写配置不够,还必须执行 AddRedisSource<T>()。
为什么一启动就报脚本目录错误
如果 ScriptPath 有值,目录就必须真实存在。
当前项目没有脚本时,直接设为空字符串最稳。
为什么 Redis 底座接好了,但登录态还是没共享
因为 Redis 底座只负责连上 Redis。
登录态共享还要继续接 RedisUserManager。