<> Basic use of static field cache
/// <summary> /// 1 Client cache -CDN cache - Reverse proxy caching - Local cache /// 2 Principle of local cache and implementation of handwriting Foundation /// 3
Cache update / be overdue / Multithreading test /// 4 Summary of cache class library encapsulation and cache application /// </summary> /// <param name="args"></param>
static void Main(string[] args) { try { Console.WriteLine(" Advanced development / Transmutation architecture !"); {
Console.WriteLine("***************DBHelper*****************"); for (int i = 0; i
< 5; i++) // Query data repeatedly { Console.WriteLine($" obtain {nameof(DBHelper)} {i} second
{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
(); } /// <summary> /// Simulate database query /// </summary> public class DBHelper { ///
<summary> /// 1 Time consuming and resource consuming /// 2 When the parameter is fixed , The results remain unchanged /// </summary> /// <typeparam
name="T"></typeparam> /// <param name="index"></param> /// <returns></returns>
public static List<T> Query<T>(int index) { Console.WriteLine("This is {0}
Query", typeof(DBHelper)); long lResult = 0; // Time consuming and resource consuming for (int i = index; i < 1
_000_000_000; i++) { lResult += i; } /// as long as Index unchanged The return value is invariant ! List<T> tList = new
List<T>(); for (int i = 0; i < index % 3; i++) { tList.Add(default(T)); } return
tList; } } public class CustomCache { /// <summary> /// Dictionary cache ///
static: Will not be Gc recovery ; /// Private: No outside access to him /// </summary> 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 Cache encapsulation
/// <summary> /// Cache manager interface /// </summary> public interface
ICache { /// <summary> /// Gets or sets the value associated with the specified
key. /// </summary> /// <typeparam name="T">Type</typeparam> /// <param
name="key">The key of the value to get.</param> /// <returns>The value
associated with the specified key.</returns> T Get<T>(string key); /// <summary>
/// Adds the specified key and object to the cache. /// </summary> /// <param
name="key">key</param> /// <param name="data">Data</param> /// <param
name="cacheTime">Cache time</param> void Add(string key, object data, int
cacheTime= 30); /// <summary> /// Gets a value indicating whether the value
associated with the specified key is cached /// </summary> /// <param
name="key">key</param> /// <returns>Result</returns> bool Contains(string key);
/// <summary> /// Removes the value with the specified key from the cache ///
</summary> /// <param name="key">/key</param> void Remove(string key); ///
<summary> /// Clear all cache data /// </summary> void RemoveAll(); object this[
string key] { get; set; } int Count { get; } } /// <summary> ///
MemoryCacheCache /// </summary> public class MemoryCacheCache : ICache { public
MemoryCacheCache() { } protected ObjectCache Cache { get { return MemoryCache.
Default; } } /// <summary> /// Read cache /// </summary> /// <typeparam
name="T"></typeparam> /// <param name="key"></param> /// <returns></returns>
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];
} /// <summary> /// Increase cache /// </summary> /// <param name="key"></param> ///
<param name="data"></param> /// <param name="cacheTime"> minute </param> 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); }
/// <summary> /// Is it included /// </summary> /// <param name="key"></param> ///
<returns></returns> public bool Contains(string key) { return Cache.Contains(key
); } public int Count { get { return (int)(Cache.GetCount()); } } /// <summary>
/// Single clear /// </summary> /// <param name="key">/key</param> public void Remove(
string key) { Cache.Remove(key); } /// <summary> /// Regular expression removal /// </summary> ///
<param name="pattern">pattern</param> 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); } } /// <summary> ///
Return cache data according to key value /// </summary> /// <param name="key"></param> /// <returns></returns>
public object this[string key] { get { return Cache.Get(key); } set { Add(key,
value); } } /// <summary> /// Clear all data /// </summary> public void RemoveAll() {
foreach (var item in Cache) Remove(item.Key); } }
<> Cache management center
public class CacheManager { #region Identity private CacheManager() { } private
static ICache cache = null; static CacheManager() { Console.WriteLine(
" Start initialization of cache ....."); // You can create different cache object cache = (ICache)Activator.CreateInstance(
typeof(MemoryCacheCache)); // Here you can choose according to the configuration file //cache =
(ICache)Activator.CreateInstance(typeof(CustomerCache)); } #endregion Identity #
region ICache /// <summary> /// Number of current cache data items /// </summary> public static int
Count{ get { return cache.Count; } } /// <summary> /// If the data item key value already exists in the cache , Return to true
/// </summary> /// <param name="key"> Key value of data item </param> ///
<returns> Does the data item exist </returns> public static bool Contains(string key) { return
cache.Contains(key); } /// <summary> /// Get cache data /// </summary> /// <param
name="key"></param> /// <returns></returns> public static T GetData<T>(string
key) { return cache.Get<T>(key); } /// <summary> /// /// </summary> ///
<typeparam name="T"></typeparam> /// <param name="key"> Cached items </param> /// <param
name="acquire"> How to get data when there is no cache </param> /// <param name="cacheTime"> Unit minute
default 30</param> /// <returns></returns> 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); } ///
<summary> /// Add cache data . /// If another data with the same key value already exists , The original data item will be deleted , New data item added . /// </summary> ///
<param name="key"> Key value of cache data </param> /// <param name="value"> Cached data , Can be used for null value </param>
/// <param name="expiratTime"> Cache expiration interval ( Company : minute )</param> public static void Add(
string key, object value, int expiratTime = 30) { if (Contains(key)) cache.
Remove(key); cache.Add(key, value, expiratTime); } /// <summary> /// Delete cache data item
/// </summary> /// <param name="key"></param> public static void Remove(string
key) { cache.Remove(key); } /// <summary> /// Delete all cached data items /// </summary> public
static void RemoveAll() { cache.RemoveAll(); } #endregion }
Cache optimization
/// <summary> /// Never expire : Right now /// Absolute Expiration : After how long , It's overdue It won't work ///
Slide expiration : After setting the expiration time , If used within the validity period , Just slide back /// 1.Value; data ; /// 2. Expiration point : /// 3. Sliding time ///
ordinary cache /// </summary> public class CustomCache { static CustomCache() //CLR call
The entire process is executed and only once { Task.Run(() => // { while (true) // Dead loop to judge { 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; } } }); } /// <summary>
/// static: Will not be Gc recovery ; /// Private: No outside access to him /// </summary> private static Dictionary
<string, DataModel> CustomCacheDictionary = new Dictionary<string, DataModel>();
private static readonly object obj_Lock = new object(); /// <summary> ///
By default, you do not expire /// </summary> /// <param name="key"></param> /// <param
name="value"></param> public static void Add(string key, object value) { lock (
obj_Lock) CustomCacheDictionary.Add(key, new DataModel() { Value = value,
ObsloteType= ObsloteType.Never }); } /// <summary> /// Absolute Expiration /// </summary> ///
<param name="key"></param> /// <param name="value"></param> /// <param
name="timeOutSecond"></param> 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 }); ; ; } // Clear all caches , bring disaster to the fish in the moat !
public static void RemoveAll() { lock (obj_Lock) CustomCacheDictionary.Clear();
// Everything in the dictionary has been cleaned up } 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; } } /// <summary>
/// Thread safety cache /// </summary> public class CustomCacheNew { static CustomCacheNew
() // { Task.Run(() => // { while (true) // Dead loop to judge { try { //Thread.Sleep(60 *
1000 * 10); // Cache cleanup starts in ten minutes 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; } } }); } ///
<summary> /// static: Will not be Gc recovery ; /// Private: He was not allowed to visit outside /// /// Thread safety dictionary /// </summary>
private static ConcurrentDictionary<string, DataModel> CustomCacheDictionary =
new ConcurrentDictionary<string, DataModel>(); /// <summary> /// By default, you do not expire ///
</summary> /// <param name="key"></param> /// <param name="value"></param>
public static void Add(string key, object value) { CustomCacheDictionary.TryAdd(
key, new DataModel() { Value = value, ObsloteType = ObsloteType.Never }); } ///
<summary> /// Absolute Expiration /// </summary> /// <param name="key"></param> /// <param
name="value"></param> /// <param name="timeOutSecond"></param> 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 }
); ; ; } // Clear all caches , bring disaster to the fish in the moat ! public static void RemoveAll() { CustomCacheDictionary.
Clear();// Everything in the dictionary has been cleaned up } 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; } ///
<summary> /// Judge whether it exists or not /// </summary> /// <param name="key"></param> ///
<returns></returns> 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 } /// <summary>
/// Solving performance issues /// </summary> 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;// Simulation acquisition CPU Number of slices
// Dynamic dictionary generation for (int i = 0; i < CupNum; i++) { dicCacheList.Add(new Dictionary<
string, DataModel>()); //CPU How many are there Just a few dictionaries lockList.Add(new object());// No dictionary corresponds to a lock }
Task.Run(() => // { while (true) // Dead loop to judge { try { for (int i = 0; i < CupNum; i
++) { lock (lockList[i]) { //Thread.Sleep(60 * 1000 * 10); // Cache cleanup starts in ten minutes 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; } } }); } /// <summary> /// By default, you do not expire
/// </summary> /// <param name="key"></param> /// <param name="value"></param>
public static void Add(string key, object value) { int hash = key.GetHashCode()
* (-1); // As long as the string changes ,hash The value does not change ! int index = hash % CupNum; lock (lockList[index])
dicCacheList[index].Add(key, new DataModel() { Value = value, ObsloteType =
ObsloteType.Never }); } /// <summary> /// Absolute Expiration /// </summary> /// <param
name="key"></param> /// <param name="value"></param> /// <param
name="timeOutSecond"></param> public static void Add(string key, object value,
int timeOutSecond) //3000 { int hash = key.GetHashCode() * (-1);
// As long as the string changes ,hash The value does not change ! 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); // As long as the string changes ,hash The value does not change ! 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 }); ; ; } // Clear all caches , bring disaster to the fish in the moat ! 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); // As long as the string changes ,hash The value does not change ! 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); // As long as the string changes ,hash The value does not change ! int index = hash % CupNum; return (T)(dicCacheList[
index][key]).Value; } /// <summary> /// Judge whether it exists or not /// </summary> /// <param
name="key"></param> /// <returns></returns> public static bool Exists(string key
) { int hash = key.GetHashCode() * (-1); // As long as the string changes ,hash The value does not change ! 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; } }

Technology