///
/// 1 客户端缓存-CDN缓存-反向代理缓存-本地缓存
/// 2 本地缓存原理和手写基础实现
/// 3 缓存更新/过期/多线程测试
/// 4 缓存类库封装和缓存应用总结
///
///
static void Main(string[] args)
{
try
{
Console.WriteLine("开发进阶/蜕变架构!");
{
Console.WriteLine("***************DBHelper*****************");
for (int i = 0; i < 5; i++) //会重复查询数据
{
Console.WriteLine($"获取{nameof(DBHelper)} {i}次 {DateTime.Now.ToString("yyyyMMdd HHmmss.fff")}");
List<Program> programList = null;
string key = $"{nameof(Program)}_DBHelper.Query_{123}";
programList = CustomCache.GetT<List<Program>>(key, () =>
{
return DBHelper.Query<Program>(123);
});
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
///
///模拟数据库查询
///
public class DBHelper
{
///
/// 1 耗时耗资源
/// 2 参数固定时,结果不变
///
///
///
///
public static List<T> Query<T>(int index)
{
Console.WriteLine("This is {0} Query", typeof(DBHelper));
long lResult = 0;
//耗时耗资源
for (int i = index; i < 1_000_000_000; i++)
{
lResult += i;
}
///只要Index不变 返回值是不变的!
List<T> tList = new List<T>();
for (int i = 0; i < index % 3; i++)
{
tList.Add(default(T));
}
return tList;
}
}
public class CustomCache
{
///
/// 字典缓存
/// static:不会被Gc回收;
/// Private:不让外部访问他
///
private static Dictionary<string, object> CustomCacheDictionary = new Dictionary<string, object>();
public static void Add(string key, object value)
{
CustomCacheDictionary.Add(key, value);
}
public static T Get<T>(string key)
{
return (T)CustomCacheDictionary[key];
}
public static bool Exists(string key)
{
return CustomCacheDictionary.ContainsKey(key);
}
public static T GetT<T>(string key, Func<T> func)
{
T t = default(T);
if (!Exists(key))
{
t = func.Invoke();
Add(key, t);
}
else
{
t = Get<T>(key);
}
return t;
}
}
///
/// Cache manager interface
///
public interface ICache
{
///
/// Gets or sets the value associated with the specified key.
///
/// Type
/// The key of the value to get.
/// The value associated with the specified key.
T Get<T>(string key);
///
/// Adds the specified key and object to the cache.
///
/// key
/// Data
/// Cache time
void Add(string key, object data, int cacheTime = 30);
///
/// Gets a value indicating whether the value associated with the specified key is cached
///
/// key
/// Result
bool Contains(string key);
///
/// Removes the value with the specified key from the cache
///
/// /key
void Remove(string key);
///
/// Clear all cache data
///
void RemoveAll();
object this[string key] { get; set; }
int Count { get; }
}
///
/// MemoryCacheCache
///
public class MemoryCacheCache : ICache
{
public MemoryCacheCache() { }
protected ObjectCache Cache
{
get
{
return MemoryCache.Default;
}
}
///
/// 读取缓存
///
///
///
///
public T Get<T>(string key)
{
if (Cache.Contains(key))
{
return (T)Cache[key];
}
else
{
return default(T);
}
}
public object Get(string key)
{
return Cache[key];
}
///
/// 增加缓存
///
///
///
/// 分钟
public void Add(string key, object data, int cacheTime = 30)
{
if (data == null)
return;
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
Cache.Add(new CacheItem(key, data), policy);
}
///
/// 是否包含
///
///
///
public bool Contains(string key)
{
return Cache.Contains(key);
}
public int Count { get { return (int)(Cache.GetCount()); } }
///
/// 单个清除
///
/// /key
public void Remove(string key)
{
Cache.Remove(key);
}
///
/// 正则表达式移除
///
/// pattern
public void RemoveByPattern(string pattern)
{
var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
var keysToRemove = new List<String>();
foreach (var item in Cache)
if (regex.IsMatch(item.Key))
keysToRemove.Add(item.Key);
foreach (string key in keysToRemove)
{
Remove(key);
}
}
///
/// 根据键值返回缓存数据
///
///
///
public object this[string key]
{
get { return Cache.Get(key); }
set { Add(key, value); }
}
///
/// 清除全部数据
///
public void RemoveAll()
{
foreach (var item in Cache)
Remove(item.Key);
}
}
public class CacheManager
{
#region Identity
private CacheManager()
{ }
private static ICache cache = null;
static CacheManager()
{
Console.WriteLine("开始缓存的初始化.....");
//可以创建不同的cache对象
cache = (ICache)Activator.CreateInstance(typeof(MemoryCacheCache));
// 这里可以根据配置文件来选择
//cache = (ICache)Activator.CreateInstance(typeof(CustomerCache));
}
#endregion Identity
#region ICache
///
/// 当前缓存数据项的个数
///
public static int Count
{
get { return cache.Count; }
}
///
/// 如果缓存中已存在数据项键值,则返回true
///
/// 数据项键值
/// 数据项是否存在
public static bool Contains(string key)
{
return cache.Contains(key);
}
///
/// 获取缓存数据
///
///
///
public static T GetData<T>(string key)
{
return cache.Get<T>(key);
}
///
///
///
///
/// 缓存的项
/// 没有缓存的时候获取数据的方式
/// 单位分钟 默认30
///
public static T Get<T>(string key, Func<T> acquire, int cacheTime = 30)
{
if (!cache.Contains(key))
{
T result = acquire.Invoke();
cache.Add(key, result, cacheTime);
}
return GetData<T>(key);
}
///
/// 添加缓存数据。
/// 如果另一个相同键值的数据已经存在,原数据项将被删除,新数据项被添加。
///
/// 缓存数据的键值
/// 缓存的数据,可以为null值
/// 缓存过期时间间隔(单位:分钟)
public static void Add(string key, object value, int expiratTime = 30)
{
if (Contains(key))
cache.Remove(key);
cache.Add(key, value, expiratTime);
}
///
/// 删除缓存数据项
///
///
public static void Remove(string key)
{
cache.Remove(key);
}
///
/// 删除所有缓存数据项
///
public static void RemoveAll()
{
cache.RemoveAll();
}
#endregion
}
缓存优化
///
/// 永不过期:当前就是
/// 绝对过期:过了多长时间以后,就过期了 就不能用了
/// 滑动过期:设定好过期时间后,如果在有效期内使用过,就往后滑动
/// 1.Value;数据;
/// 2.过期时间点:
/// 3.滑动时间
/// 普通cache
///
public class CustomCache
{
static CustomCache() //CLR调用 整个进程执行且只执行一次
{
Task.Run(() => //
{
while (true) //死循环来判断
{
try
{
List<string> delKeyList = new List<string>();
lock (obj_Lock)
{
foreach (var key in CustomCacheDictionary.Keys)
{
DataModel model = CustomCacheDictionary[key];
if (model.Deadline < DateTime.Now && model.ObsloteType != ObsloteType.Never)
{
delKeyList.Add(key);
}
}
}
delKeyList.ForEach(key => Remove(key));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
});
}
///
/// static:不会被Gc回收;
/// Private:不让外部访问他
///
private static Dictionary<string, DataModel> CustomCacheDictionary = new Dictionary<string, DataModel>();
private static readonly object obj_Lock = new object();
///
/// 默认你是不过期
///
///
///
public static void Add(string key, object value)
{
lock (obj_Lock)
CustomCacheDictionary.Add(key, new DataModel()
{
Value = value,
ObsloteType = ObsloteType.Never
});
}
///
/// 绝对过期
///
///
///
///
public static void Add(string key, object value, int timeOutSecond) //3000
{
lock (obj_Lock)
CustomCacheDictionary.Add(key, new DataModel()
{
Value = value,
ObsloteType = ObsloteType.Absolutely,
Deadline = DateTime.Now.AddSeconds(timeOutSecond)
}); ;
}
public static void Add(string key, object value, TimeSpan durtion)
{
lock (obj_Lock)
CustomCacheDictionary.Add(key, new DataModel()
{
Value = value,
ObsloteType = ObsloteType.Relative,
Deadline = DateTime.Now.Add(durtion),
Duraton = durtion
}); ; ;
}
//清楚所有缓存,殃及池鱼!
public static void RemoveAll()
{
lock (obj_Lock)
CustomCacheDictionary.Clear();//字典中的所有内容全部被清理到
}
public static void Remove(string key)
{
lock (obj_Lock)
CustomCacheDictionary.Remove(key);
}
public static void RemoveCondition(Func<string, bool> func)
{
List<string> keyList = new List<string>();
lock (obj_Lock)
foreach (var key in CustomCacheDictionary.Keys)
{
if (func.Invoke(key))
{
keyList.Add(key);
}
}
keyList.ForEach(s => Remove(s));
}
public static T Get<T>(string key)
{
return (T)(CustomCacheDictionary[key]).Value;
}
public static bool Exists(string key)
{
if (CustomCacheDictionary.ContainsKey(key))
{
DataModel model = CustomCacheDictionary[key];
if (model.ObsloteType == ObsloteType.Never)
{
return true;
}
else if (model.Deadline < DateTime.Now) //
{
lock (obj_Lock)
{
CustomCacheDictionary.Remove(key);
return false;
}
}
else
{
if (model.ObsloteType == ObsloteType.Relative)
{
model.Deadline = DateTime.Now.Add(model.Duraton);
}
return true;
}
}
else
{
return false;
}
}
public static T GetT<T>(string key, Func<T> func)
{
T t = default(T);
if (!Exists(key))
{
t = func.Invoke();
Add(key, t);
}
else
{
t = Get<T>(key);
}
return t;
}
}
///
/// 线程安全cache
///
public class CustomCacheNew
{
static CustomCacheNew() //
{
Task.Run(() => //
{
while (true) //死循环来判断
{
try
{
//Thread.Sleep(60 * 1000 * 10); //十分钟后开始清理缓存
List<string> delKeyList = new List<string>();
foreach (var key in CustomCacheDictionary.Keys)
{
DataModel model = CustomCacheDictionary[key];
if (model.Deadline < DateTime.Now && model.ObsloteType != ObsloteType.Never) //
{
delKeyList.Add(key);
}
}
delKeyList.ForEach(key => Remove(key));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
});
}
///
/// static:不会被Gc回收;
/// Private:不让外部访问他
///
/// 线程安全字典
///
private static ConcurrentDictionary<string, DataModel> CustomCacheDictionary = new ConcurrentDictionary<string, DataModel>();
///
/// 默认你是不过期
///
///
///
public static void Add(string key, object value)
{
CustomCacheDictionary.TryAdd(key, new DataModel()
{
Value = value,
ObsloteType = ObsloteType.Never
});
}
///
/// 绝对过期
///
///
///
///
public static void Add(string key, object value, int timeOutSecond) //3000
{
CustomCacheDictionary.TryAdd(key, new DataModel()
{
Value = value,
ObsloteType = ObsloteType.Absolutely,
Deadline = DateTime.Now.AddSeconds(timeOutSecond)
}); ;
}
public static void Add(string key, object value, TimeSpan durtion)
{
CustomCacheDictionary.TryAdd(key, new DataModel()
{
Value = value,
ObsloteType = ObsloteType.Relative,
Deadline = DateTime.Now.Add(durtion),
Duraton = durtion
}); ; ;
}
//清楚所有缓存,殃及池鱼!
public static void RemoveAll()
{
CustomCacheDictionary.Clear();//字典中的所有内容全部被清理到
}
public static void Remove(string key)
{
DataModel data = null;
CustomCacheDictionary.TryRemove(key, out data);
}
public static T Get<T>(string key)
{
return (T)(CustomCacheDictionary[key]).Value;
}
///
/// 判断是否存在
///
///
///
public static bool Exists(string key)
{
if (CustomCacheDictionary.ContainsKey(key))
{
DataModel model = CustomCacheDictionary[key];
if (model.ObsloteType == ObsloteType.Never)
{
return true;
}
else if (model.Deadline < DateTime.Now) //
{
DataModel data = null;
CustomCacheDictionary.TryRemove(key, out data);
return false;
}
else
{
if (model.ObsloteType == ObsloteType.Relative)
{
model.Deadline = DateTime.Now.Add(model.Duraton);
}
return true;
}
}
else
{
return false;
}
}
public static T GetT<T>(string key, Func<T> func)
{
T t = default(T);
if (!Exists(key))
{
t = func.Invoke();
Add(key, t);
}
else
{
t = Get<T>(key);
}
return t;
}
}
internal class DataModel
{
public object Value { get; set; }
public ObsloteType ObsloteType { get; set; }
public DateTime Deadline { get; set; }
public TimeSpan Duraton { get; set; }
}
public enum ObsloteType
{
Never,
Absolutely,
Relative
}
///
/// 解决性能问题
///
public class CustomCacheNewproblem
{
private static List<Dictionary<string, DataModel>> dicCacheList = new List<Dictionary<string, DataModel>>();
private static List<object> lockList = new List<object>();
public static int CupNum = 0;
static CustomCacheNewproblem()
{
CupNum = 3;//模拟获取获取CPU片数
//动态生成字典
for (int i = 0; i < CupNum; i++)
{
dicCacheList.Add(new Dictionary<string, DataModel>()); //CPU 有几片 就来几个字典
lockList.Add(new object());//没个字典对应一个锁
}
Task.Run(() => //
{
while (true) //死循环来判断
{
try
{
for (int i = 0; i < CupNum; i++)
{
lock (lockList[i])
{
//Thread.Sleep(60 * 1000 * 10); //十分钟后开始清理缓存
List<string> delKeyList = new List<string>();
foreach (var key in dicCacheList[i].Keys)
{
DataModel model = dicCacheList[i][key];
if (model.Deadline < DateTime.Now && model.ObsloteType != ObsloteType.Never) //
{
delKeyList.Add(key);
}
}
delKeyList.ForEach(key => dicCacheList[i].Remove(key));
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
});
}
///
/// 默认你是不过期
///
///
///
public static void Add(string key, object value)
{
int hash = key.GetHashCode() * (-1); //只要字符串变,hash值不变!
int index = hash % CupNum;
lock (lockList[index])
dicCacheList[index].Add(key, new DataModel()
{
Value = value,
ObsloteType = ObsloteType.Never
});
}
///
/// 绝对过期
///
///
///
///
public static void Add(string key, object value, int timeOutSecond) //3000
{
int hash = key.GetHashCode() * (-1); //只要字符串变,hash值不变!
int index = hash % CupNum;
lock (lockList[index])
dicCacheList[index].Add(key, new DataModel()
{
Value = value,
ObsloteType = ObsloteType.Absolutely,
Deadline = DateTime.Now.AddSeconds(timeOutSecond)
}); ;
}
public static void Add(string key, object value, TimeSpan durtion)
{
int hash = key.GetHashCode() * (-1); //只要字符串变,hash值不变!
int index = hash % CupNum;
lock (lockList[index])
dicCacheList[index].Add(key, new DataModel()
{
Value = value,
ObsloteType = ObsloteType.Relative,
Deadline = DateTime.Now.Add(durtion),
Duraton = durtion
}); ; ;
}
//清楚所有缓存,殃及池鱼!
public static void RemoveAll()
{
for (int i = 0; i < CupNum; i++)
{
dicCacheList[i].Clear();
}
}
public static void Remove(string key)
{
int hash = key.GetHashCode() * (-1); //只要字符串变,hash值不变!
int index = hash % CupNum;
if (dicCacheList[index].ContainsKey(key))
{
dicCacheList[index].Remove(key);
}
}
public static T Get<T>(string key)
{
int hash = key.GetHashCode() * (-1); //只要字符串变,hash值不变!
int index = hash % CupNum;
return (T)(dicCacheList[index][key]).Value;
}
///
/// 判断是否存在
///
///
///
public static bool Exists(string key)
{
int hash = key.GetHashCode() * (-1); //只要字符串变,hash值不变!
int index = hash % CupNum;
if (dicCacheList[index].ContainsKey(key))
{
DataModel model = dicCacheList[index][key];
if (model.ObsloteType == ObsloteType.Never)
{
return true;
}
else if (model.Deadline < DateTime.Now) //
{
dicCacheList[index].Remove(key);
return false;
}
else
{
if (model.ObsloteType == ObsloteType.Relative)
{
model.Deadline = DateTime.Now.Add(model.Duraton);
}
return true;
}
}
else
{
return false;
}
}
public static T GetT<T>(string key, Func<T> func)
{
T t = default(T);
if (!Exists(key))
{
t = func.Invoke();
Add(key, t);
}
else
{
t = Get<T>(key);
}
return t;
}
}