Files
KinginfoGateway/src/Admin/ThingsGateway.NewLife.X/Caching/Readme.MD
2025-10-15 17:40:33 +08:00

4.9 KiB
Raw Blame History

缓存架构以ICache接口为核心包括MemoryCache、Redis和DbCache实现
后续例程与使用说明均以Redis为例各缓存实现类似。

内存缓存 MemoryCache

MemoryCache核心是并发字典NonBlockingDictionary由于省去了序列化和网络通信使得它具有千万级超高性能。
MemoryCache支持过期时间默认容量10万个未过期key超过该值后每60秒根据LRU清理溢出部分。
常用于进程内千万级以下数据缓存场景。

// 缓存默认实现Cache.Default是MemoryCache可修改
//var ic = Cache.Default;
//var ic = new MemoryCache();

基础 Redis

Redis实现标准协议以及基础字符串操作完整实现由独立开源项目NewLife.Redis提供。
采取连接池加同步阻塞架构具有超低延迟200~600us以及超高吞吐量的特点。
在物流行业大数据实时计算中广泛应有经过日均100亿次调用量验证。

// 实例化Redis默认端口6379可以省略密码有两种写法
//var ic = new Redis("127.0.0.1", 7);
var ic = new Redis("pass@127.0.0.1:6379", 7);
//var ic = new Redis("server=127.0.0.1:6379;password=pass", 7);
ic.Log = XTrace.Log; // 调试日志。正式使用时注释

数据库 DbCache

DbCache属于实验性质采用数据库存储数据默认SQLite。

基本操作

在基本操作之前,我们先做一些准备工作:

  • 新建控制台项目,并在入口函数开头加上 XTrace.UseConsole(); ,这是为了方便查看调试日志
  • 具体测试代码之前需要加上前面MemoryCache或Redis的实例化代码
  • 准备一个模型类User
class User
{
    public String Name { get; set; }
    public DateTime CreateTime { get; set; }
}

添删改查:

var user = new User { Name = "NewLife", CreateTime = DateTime.Now };
ic.Set("user", user, 3600);
var user2 = ic.Get<User>("user");
XTrace.WriteLine("Json: {0}", ic.Get<String>("user"));
if (ic.ContainsKey("user")) XTrace.WriteLine("存在!");
ic.Remove("user");

执行结果:

14:14:25.990  1 N - SELECT 7
14:14:25.992  1 N - => OK
14:14:26.008  1 N - SETEX user 3600 [53]
14:14:26.021  1 N - => OK
14:14:26.042  1 N - GET user
14:14:26.048  1 N - => [53]
14:14:26.064  1 N - GET user
14:14:26.065  1 N - => [53]
14:14:26.066  1 N - Json: {"Name":"NewLife","CreateTime":"2018-09-25 14:14:25"}
14:14:26.067  1 N - EXISTS user
14:14:26.068  1 N - => 1
14:14:26.068  1 N - 存在!
14:14:26.069  1 N - DEL user
14:14:26.070  1 N - => 1

保存复杂对象时默认采用Json序列化所以上面可以按字符串把结果取回来发现正是Json字符串。
Redis的strings实质上就是带有长度前缀的二进制数据[53]表示一段53字节长度的二进制数据。

集合操作

GetAll/SetAll 在Redis上是很常用的批量操作同时获取或设置多个key一般有10倍以上吞吐量。

批量操作:

var dic = new Dictionary<String, Object>
{
    ["name"] = "NewLife",
    ["time"] = DateTime.Now,
    ["count"] = 1234
};
ic.SetAll(dic, 120);

var vs = ic.GetAll<String>(dic.Keys);
XTrace.WriteLine(vs.Join(",", e => $"{e.Key}={e.Value}"));

执行结果:

MSET name NewLife time 2018-09-25 15:56:26 count 1234
=> OK
EXPIRE name 120
EXPIRE time 120
EXPIRE count 120
MGET name time count
name=NewLife,time=2018-09-25 15:56:26,count=1234

集合操作里面还有 GetList/GetDictionary/GetQueue/GetSet 四个类型集合分别代表Redis的列表、哈希、队列、Set集合等。
基础版Redis不支持这四个集合完整版NewLife.Redis支持MemoryCache则直接支持。

高级操作

  • Add 添加当key不存在时添加已存在时返回false。
  • Replace 替换,替换已有值为新值,返回旧值。
  • Increment 累加,原子操作
  • Decrement 递减,原子操作

高级操作:

var flag = ic.Add("count", 5678);
XTrace.WriteLine(flag ? "Add成功" : "Add失败");
var ori = ic.Replace("count", 777);
var count = ic.Get<Int32>("count");
XTrace.WriteLine("count由{0}替换为{1}", ori, count);

ic.Increment("count", 11);
var count2 = ic.Decrement("count", 10);
XTrace.WriteLine("count={0}", count2);

执行结果:

SETNX count 5678
=> 0
Add失败
GETSET count 777
=> 1234
GET count
=> 777
count由1234替换为777
INCRBY count 11
=> 788
DECRBY count 10
=> 778
count=778

性能测试

Bench 会分根据线程数分多组进行添删改压力测试。
rand 参数是否随机产生key/value。
batch 批大小分批执行读写操作借助GetAll/SetAll进行优化。

Redis默认设置AutoPipeline=100无分批时打开管道操作对添删改优化。

容器化部署

支持从环境变量 Redis_{Name} 中加载配置,用于容器化部署。