Scut:缓存管理
Scut 的缓存管理看起来还是蛮复杂的。
redis 本身就有内存缓存+持久化的作用,Scut还是自己封装了一层内存缓存+Redis缓存+持久化。
。
这是一个缩略版本的结构图。
1. 上半部分是通用的缓存池结构,用来存放各类缓存数据。
第一层Dictionary是按大类区分:Entity_{0}、Personal_(0),type.name 等;
第二层Dictionary则是进一步细分,比如同样一个type下的 type.name +"UserID";
2. 下半部分则是应用层对缓存的操作器,包含数据取用+操作方法,应用层数据结构要按照一定的规则进行封装,才能直接使用Scut提供的“带数据修改事件”的各类组件。
CacheItemSet 的作用:
Cache 们都会用 CacheItemSet 容器 来装载具体的数据;
private readonly CacheType _cacheItemType; //标记了缓存的类型,不同类型的缓存在从redis加载时key的组装方式,释放缓存的规则都不相同
private readonly bool _isReadOnly;
private CachePeriod _period; //缓存的核心:生命周期
private IDataExpired _itemData; //具体的数据
public bool HasChanged { get; private set; }
生命周期如何起作用?HasChanged 如何起作用?
在 CachePool 里的 DisposeCache 接口有统一处理,但没有发现哪里在定期有效调用?
ShareCacheStruct:
public IEnumerable<T> Take()
{
return DataContainer.ToEntityEnumerable(false);
}
public IEnumerable<T> ToEntityEnumerable(bool isLoad = false)
{
if (isLoad) CheckLoad();
return Container.GetEnumerable().Select(pari => pari.Value).OfType<CacheItemSet>().Select(itemSet => (T)itemSet.GetItem());
}
可以知道 ShareCache 从缓存加载数据时,是整块相应类型的数据全部加载出来,适合用来管理配置、处理公有数据。
PersonalCache:
public IEnumerable<T> Take()
{
return DataContainer.ToGroupEnumerable();
} public T Take(params object[] keys)
{
string key = AbstractEntity.CreateKeyCode(keys);
return DataContainer.TakeEntityFromKey(key);
}
它可以单个或整体进行缓存加载,更适合处理单用户的某类型数据。
ShareEntity 比 BaseEntity 多了一个 API:GetIdentityId() 未来有什么作用再观察。
AbstractEntity:
/// <summary>
/// 存储改变的属性集合
/// </summary>
private ConcurrentQueue<string> _changePropertys = new ConcurrentQueue<string>();
/// <summary>
/// 等待更新属性
/// </summary>
private readonly HashSet<string> _waitUpdateList = new HashSet<string>();
这两个属性,表示 abstracEntity 最重要的作用应该是“部分更新修改过的数据”
持续追踪,发现其作用是向数据库写入修改过的数据:
SqlDataSender.cs:
public bool Send<T>(params T[] dataList) where T : AbstractEntity
{
return Send(dataList, GetPropertyValue, GetPostColumns);
}
那什么时候进行写入修改数据? AbstractEntity 下的 EntityChangeEvent : IItemChangeEvent 是如何起作用的?
IItemChangeEvent:
[JsonIgnore]
public bool IsExpired { get; set; } [JsonIgnore]
public bool IsInCache { get; set; } /// <summary>
/// 是否有变更
/// </summary>
public abstract bool HasChanged { get; } /// <summary>
/// 绑定实体类的属性名(表的列名)
/// </summary>
internal abstract string PropertyName { get; set; } /// <summary>
/// 当前对象变更事件对象
/// </summary>
public abstract CacheItemChangeEvent ItemEvent { get; } /// <summary>
/// 当前对象的子类变更事件对象
/// </summary>
public abstract CacheItemChangeEvent ChildrenEvent { get; }
在 AbstractEntity 中,对本身数值进行“修改、删除进行封装的API”,都会调用事件通知 Notify。
AbstractEntity 重载的 Notify API:
protected override void Notify(object sender, CacheItemEventArgs eventArgs)
{
if (_isReadOnly || CheckChnage()) return;
_hasChanged = true;
AddChangePropertys(eventArgs.PropertyName);
PutToChangeKeys(this);
}
private void PutToChangeKeys(AbstractEntity entity)
{
if (!IsModifying)
{
//Auto trigger modify event
ProfileManager.ChangeEntityByAutoOfMessageQueueTimes(entity.GetType().FullName, entity.GetKeyCode());
DataSyncQueueManager.Send(entity);
}
}
可以看出这个位置并没有真正使用 EntityChangeEvent 机制,而是重写了 Notity(),在修改数据后,直接向底层队列压入修改队列。
最新文章
- 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(四)
- android 画虚线、实线,画圆角矩形,一半圆角
- 31. Next Permutation
- 一个把List<;String>;转化为以";,";隔开的字符串的方法
- IE11的CSS兼容性问题
- datatable列操作
- jquery 使用ajax调用c#后台方法
- Sql Server 自定义数据类型
- C#打开php链接传参然后接收返回值
- 用户关注微信公众号后,获取该用户的openID存数据库失败
- 2.5、Android Studio添加多适配的向量图片
- sitecore开发入门之如何在代码中获取SITECORE图像URL
- MySQL:(一)
- 列表 list 容器类型数据(str字符串, list列表, tuple元组, set集合, dict字典)--->;元组 tuple-->;字符串 str
- 第二弹:超全Python学习资源整理(进阶系列)
- 【LeetCode题解】160_相交链表
- 51nod 1443 路径和树(最短路)
- 禁用iPhone手机浏览器上给电话号码自动加上的link样式(苹果手机自动给手机号加样式)
- Linux使用sshfs通过ssh挂载远端机器
- 「BZOJ 5188」「Usaco2018 Jan」MooTube