1.ServiceStack.Redis 是商业版,免费版有限制;ServiceStack.Redis每小时6000次限制,ServiceStack 4.0 开始已经成为商业产品,不再完全免费,好在是开源的.

2.StackExchange.Redis 是免费版,但是内核在 .NETCore 运行有问题经常 Timeout,暂无法解决;

3.CSRedis于2016年开始支持.NETCore一直迭代至今,实现了低门槛、高性能,和分区高级玩法的.NETCore redis-cli SDK;

 

1. 通过包管理器安装CSRedis
2. 实例化csredis,并继承icasheservice
3. DBContent 里实例化csredisClient
4. TestRedisCache


public class TestRedisCache: ICacheService
{
/// <summary>
/// redis
/// </summary>
public CSRedisClient rds;

//redis cach second,default 120,read appsetting.json
int _expirySeconds = 120;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="connectionStrings"></param>
public TestRedisCache(string[] connectionStrings, int expirySeconds)
{
this.rds = new CSRedis.CSRedisClient((p => { return null; }), connectionStrings);
_expirySeconds = expirySeconds;
}

public void Add<V>(string key, V value)
{
this.rds.Set(key, value);

}

public void Add<V>(string key, V value, int cacheDurationInSeconds)
{
if (cacheDurationInSeconds >= 2147483647)
{
cacheDurationInSeconds = _expirySeconds;
}
this.rds.Set(key, value, cacheDurationInSeconds);
}

public bool ContainsKey<V>(string key)
{
return this.rds.Exists(key);
}

public V Get<V>(string key)
{
return this.rds.Get<V>(key);
}

public IEnumerable<string> GetAllKey<V>()
{
return this.rds.Keys("*");
}

public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue)
{
if (this.ContainsKey<V>(cacheKey))
{
return this.Get<V>(cacheKey);
}
else
{
var result = create();
this.Add(cacheKey, result, cacheDurationInSeconds);
return result;
}
}

public void Remove<V>(string key)
{
this.rds.Del(key);
}
public void DisposeRedis()
{
this.rds.Dispose();
}
}
}


5. DBContext

public DBContext()
{
//get mysql connnection str
var salveCount = configuration.GetSection("ConnectionStrings:SlaveCount").Value.ObjToInt();
List<SlaveConnectionConfig> slaves = new List<SlaveConnectionConfig>();
for (int i = 0; i < salveCount; i++)
{
slaves.Add(new SlaveConnectionConfig
{
ConnectionString = configuration[$"ConnectionStrings:Slave:{i}:ConnectionString"], HitRate = configuration[$"ConnectionStrings:Slave:{i}:HitRate"].ObjToInt()
});
}

//redis db default expiration Second
if (!string.IsNullOrEmpty(configuration["RedisString:DurationSecond"]))
{ CachExpirationSecond = int.Parse(configuration["RedisString:DurationSecond"]); }

string redisconn = configuration["RedisString:ConnectionHost"];

if (RedisDB == null)
{
RedisDB = new ExamRedisCache(new string[] { redisconn }, CachExpirationSecond);
}


//mysql db object
if (DB == null)
{
DB = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = configuration["ConnectionStrings:Master"],
DbType = DbType.MySql,
IsAutoCloseConnection = true,
InitKeyType = InitKeyType.Attribute,
SlaveConnectionConfigs = slaves,
ConfigureExternalServices = new ConfigureExternalServices()
{
DataInfoCacheService = RedisDB
}
});
}

//调式代码 用来打印SQL
DB.Aop.OnLogExecuting = (sql, pars) =>
{
Console.WriteLine(sql + "\r\n" +
DB.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
Console.WriteLine();
};
}

 

-----------------csRedis-------------

void Test()
{

CsRedisHelper.Set("name", "祝雷");//设置值。默认永不过期
//aaaaa.SetAsync("name", "祝雷");//异步操作
Console.WriteLine(CsRedisHelper.Get<String>("name"));

CsRedisHelper.Set("time", DateTime.Now, 1);
Console.WriteLine(CsRedisHelper.Get<DateTime>("time"));

Console.WriteLine(CsRedisHelper.Get<DateTime>("time"));

// 列表
CsRedisHelper.RPush("list", "第一个元素");
CsRedisHelper.RPush("list", "第二个元素");
CsRedisHelper.LInsertBefore("list", "第二个元素", "我是新插入的第二个元素!");
Console.WriteLine($"list的长度为{CsRedisHelper.LLen("list")}");
//Console.WriteLine($"list的长度为{aaaaa.LLenAsync("list")}");//异步
Console.WriteLine($"list的第二个元素为{CsRedisHelper.LIndex("list", 1)}");
//Console.WriteLine($"list的第二个元素为{aaaaa.LIndexAsync("list",1)}");//异步
// 哈希
CsRedisHelper.HSet("person", "name", "zhulei");
CsRedisHelper.HSet("person", "sex", "男");
CsRedisHelper.HSet("person", "age", "28");
CsRedisHelper.HSet("person", "adress", "hefei");
Console.WriteLine($"person这个哈希中的age为{CsRedisHelper.HGet<int>("person", "age")}");
//Console.WriteLine($"person这个哈希中的age为{aaaaa.HGetAsync<int>("person", "age")}");//异步


// 集合
CsRedisHelper.SAdd("students", "zhangsan", "lisi");
CsRedisHelper.SAdd("students", "wangwu");
CsRedisHelper.SAdd("students", "zhaoliu");
Console.WriteLine($"students这个集合的大小为{CsRedisHelper.SCard("students")}");
Console.WriteLine($"students这个集合是否包含wagnwu:{CsRedisHelper.SIsMember("students", "wangwu")}");

//普通订阅
RedisHelper.Subscribe(
("chan1", msg => Console.WriteLine(msg.Body)),
("chan2", msg => Console.WriteLine(msg.Body)));

//模式订阅(通配符)
RedisHelper.PSubscribe(new[] { "test*", "*test001", "test*002" }, msg => {
Console.WriteLine($"PSUB {msg.MessageId}:{msg.Body} {msg.Pattern}: chan:{msg.Channel}");
});
//模式订阅已经解决的难题:
//1、分区的节点匹配规则,导致通配符最大可能匹配全部节点,所以全部节点都要订阅
//2、本组 "test*", "*test001", "test*002" 订阅全部节点时,需要解决同一条消息不可执行多次

//发布
RedisHelper.Publish("chan1", "123123123");
//无论是分区或普通模式,RedisHelper.Publish 都可以正常通信

//不加缓存的时候,要从数据库查询
//var t1 = Test.Select.WhereId(1).ToOne();

//一般的缓存代码,如不封装还挺繁琐的
var cacheValue = RedisHelper.Get("test1");
if (!string.IsNullOrEmpty(cacheValue))
{
//try
//{
// return JsonConvert.DeserializeObject(cacheValue);
//}
//catch
//{
// //出错时删除key
// RedisHelper.Del("test1");
// throw;
//}
}
//var t1 = Test.Select.WhereId(1).ToOne();
// RedisHelper.Set("test1", JsonConvert.SerializeObject(t1), 10); //缓存10秒

//使用缓存壳效果同上,以下示例使用 string 和 hash 缓存数据
//var t1 = RedisHelper.CacheShell("test1", 10, () => Test.Select.WhereId(1).ToOne());
//var t2 = RedisHelper.CacheShell("test", "1", 10, () => Test.Select.WhereId(1).ToOne());
//var t3 = RedisHelper.CacheShell("test", new[] { "1", "2" }, 10, notCacheFields => new[] {
// ("1", Test.Select.WhereId(1).ToOne()),
// ("2", Test.Select.WhereId(2).ToOne())
// });
}