CYQ.Data V5 分布式缓存MemCached应用开发介绍
今天大伙还在热议关于.NET Core的东西,我只想说一句:在.NET 跨平台叫了这么多年间,其实人们期待的是一个知名的跨平台案例,而不是一堆能跨平台的消息。
好,回头说说框架:
在框架完成数据库读写分离的功能后,开始回想起2年前所构思的:关于框架集成分布式缓存MemCached的实现。
之前一直没动手,是因为思路比较飘,秉承着框架应该简单干净轻量引用无依赖和使用不复杂的思维:
看着MemCached的服务端协议,整天思考着自己用Socket写一个客户端。
后来可能是没激情,迟迟没动手。
又在某个时刻,想过偷懒,想动态反射Memcached.ClientLibrary库,但一看到它竟然关联了四个dll,我那纯洁的心就有点抗拒它了。
所以日子就这样飘来复去,这个功能被想起又遗忘......
框架集成MemCache这几天,翻看了往昔下载的的相关源码中,有个叫BeITMemcached,扫了一下源码,发现简单轻量没外部引用。
于是就开始改造,并测试了一下,没发现问题,于是开始思考集成的方式。
框架的缓存类本来很孤单,只有一个:CacheManage.cs
现在改造完,多了10个类,编绎后dll大小多了30K,说多了也是泪~:
框架的代码重构思维 最终定案的重构思维:1:原有的CacheManage类变更为LocalCache。
2:CacheManage类变更为抽象类
3:新增MemCache,并和LocalCache一并实现CacheManage抽象类方法。
以上三步,就是核心的思维。
一开始的重构思维:1:从原有的CacheManage里提取接口ICache
2:CacheManage改名WebCache并继承自ICache(由于提口提取自本类,所以代码不需要怎么调整)
3:新建MemCache继承并实现ICache接口。
4:新建CacheManage类,并从WebCache处把Instance实例属性移到此类中,并返回对应的ICache接口。
编绎后发现:因为原来的代码有一小部分是这样写的:CacheManage cache=CacheManage.Instance;
因为返回的类型不一样,原有代码受到影响,必须改成:ICache cache=CacheManage.Instance。
为了避开影响不用改动代码,所以最终改用定案里抽象类和抽象方法实现。
下面贴一下抽象类CacheManage的方法:/// 返回唯一实例(根据是否配置AppConfig.Cache.MemCacheServers的服务器决定启用本地缓存或分布式缓存)
public abstract void Add(string key, object value, string fileName, double cacheMinutes);
public abstract void Add(string key, object value, string fileName, double cacheMinutes, CacheItemPriority level);
这里新增对外一个属性:LocalInstance,是因为一但配置了AppConfig.Cache.MemCacheServers后:
原有的本机缓存就自动切换到分布式缓存,为了使用本机缓存依旧可以使用,所以提供LocalInstance属性。
一开始是对外三个:Instance(自动切换型)、LocalInstance、MemInstance。
大伙可以思考一下,为什么MemInstance被去掉了?感觉有点说不清道不明的感觉。
由于LocalCache是变更名称自CacheManage,而CacheManage在以前文章贴过源码,所以不重复了。
现在贴一下MemCache的源码:1 /// summary 2 /// 分布式缓存类 3 /// /summary 4 internal class MemCache : CacheManage 6 MemcachedClient client; 7 internal MemCache() 9 MemcachedClient.Setup("MyCache", AppConfig.Cache.MemCacheServers.Split(,)); 10 client = MemcachedClient.GetInstance("MyCache"); 12 } 14 public override void Add(string key, object value, double cacheMinutes) 15 { 16 client.Add(key, value, DateTime.Now.AddMinutes(cacheMinutes)); 17 } 18 public override void Add(string key, object value, string fileName, double cacheMinutes) 19 { 20 client.Add(key, value, DateTime.Now.AddMinutes(cacheMinutes)); 21 } 23 public override void Add(string key, object value, string fileName) 24 { 25 client.Add(key, value); 26 } 28 public override void Add(string key, object value) 29 { 30 client.Add(key, value); 31 } 33 public override void Add(string key, object value, string fileName, double cacheMinutes, CacheItemPriority level) 34 { 35 client.Add(key, value, DateTime.Now.AddMinutes(cacheMinutes)); 36 } 38 public override Dictionary string, CacheDependencyInfo CacheInfo 39 { 40 get { return null; } 41 } 42 DateTime allowCacheTableTime = DateTime.Now; 43 private MDataTable cacheTable = null; 44 public override MDataTable CacheTable 45 { 46 get 47 { 48 if (cacheTable == null || DateTime.Now allowCacheTableTime) 49 { 50 cacheTable = null; 51 cacheTable = new MDataTable(); 52 Dictionary string, Dictionary string, string status = client.Stats(); 53 if (status != null) 54 { 56 foreach (KeyValuePair string, Dictionary string, string item in status) 57 { 58 if (item.Value.Count 0) 59 { 60 MDataTable dt = MDataTable.CreateFrom(item.Value); 61 if (cacheTable.Columns.Count == 0)//第一次 62 { 63 cacheTable = dt; 64 } 65 else 66 { 67 cacheTable.JoinOnName = "Key"; 68 cacheTable = cacheTable.Join(dt, "Value"); 69 } 70 cacheTable.Columns["Value"].ColumnName = item.Key; 71 } 72 } 73 } 74 cacheTable.TableName = "MemCache"; 75 allowCacheTableTime = DateTime.Now.AddMinutes(1); 76 } 77 return cacheTable; 78 } 79 } 81 public override void Clear() 82 { 83 client.FlushAll(); 84 } 86 public override bool Contains(string key) 87 { 88 return Get(key) != null; 89 } 91 //int count = -1; 92 //DateTime allowGetCountTime = DateTime.Now; 93 public override int Count 94 { 95 get 96 { 97 int count = 0; 98 MDataRow row = CacheTable.FindRow("Key=curr_items"); 99 if (row != null) 100 { 101 for (int i = 1; i row.Columns.Count; i++) 102 { 103 count += int.Parse(row[i].strValue); 104 } 105 } 106 return count; 107 } 108 } 110 public override object Get(string key) 111 { 112 return client.Get(key); 113 } 116 public override bool GetFileDependencyHasChanged(string key) 117 { 118 return false; 119 } 121 public override bool GetHasChanged(string key) 122 { 123 return false; 124 } 126 public override long RemainMemoryBytes 127 { 128 get { return 0; } 129 } 131 public override long RemainMemoryPercentage 132 { 133 get { return 0; } 134 } 136 public override void Remove(string key) 137 { 138 client.Delete(key); 139 } 141 public override void Set(string key, object value) 142 { 143 client.Set(key, value); 144 } 146 public override void Set(string key, object value, double cacheMinutes) 147 { 148 client.Set(key, value, DateTime.Now.AddMinutes(cacheMinutes)); 149 } 151 public override void SetChange(string key, bool isChange) 152 { 154 } 156 public override void Update(string key, object value) 157 { 158 client.Replace(key, value); 159 } 161 DateTime allowGetWorkInfoTime = DateTime.Now; 162 string workInfo = string.Empty; 163 public override string WorkInfo 164 { 165 get 166 { 167 if (workInfo == string.Empty || DateTime.Now allowGetWorkInfoTime) 168 { 169 workInfo = null; 170 Dictionary string, Dictionary string, string status = client.Status(); 171 if (status != null) 172 { 173 JsonHelper js = new JsonHelper(false, false); 174 js.Add("OKServerCount", client.okServer.ToString()); 175 js.Add("DeadServerCount", client.errorServer.ToString()); 176 foreach (KeyValuePair string, Dictionary string, string item in status) 177 { 178 js.Add(item.Key, JsonHelper.ToJson(item.Value)); 179 } 180 js.AddBr(); 181 workInfo = js.ToString(); 182 } 183 allowGetWorkInfoTime = DateTime.Now.AddMinutes(5); 184 } 185 return workInfo; 186 } 187 } 188 }
讲完实现的过程和贴完源码,下面讲一下使用过程了:
框架里使用MemCache功能的演示 1:服务端先安装,并运行起来服务端的文件是这样的:
运行后的服务是这样的,这里开了两个服务进程,分别对应:11211和11212端口:
2:代码使用是这样的原有的使用方式不变,只是增加了一行配置,就自动切换到分布式了,是不是从单机过渡到分布式太简单了。
通常我们不在代码里配置,而是配置在:
运行的结果是这样的:
使用此框架,不管是进化到数据库读写分离,还是演进到分布式缓存,整个架构的升级过程,只需增加1行配置文件。
几年前就一直在构思,浮浮沉沉地随着框架的演进,如今顺水推舟地实现了,想想都觉得有点不可思议。
另外最后Top150大神群里,有人问我,最近写的文章有人打赏么?我只弱弱的回了一句:还没。
本文原创发表于博客园,作者为路过秋天,原文链接:http://www.cnblogs.com/cyq1162/p/5617761.html
实战干货 | 分布式多级缓存设计方案 分布式多级缓存设计方案,解决海量数据读取的性能问题,包含多级缓存的存储设计,流程设计;利用多数据副本保证数据的可用性,同时通过不同数据源特点提供更高性能、更多场景数据差异化的支持
同一服务器上有多个 WordPress 网站如何配置 Memcached 缓存? 如果在同一台服务器上,部署了多个 Wordpress 项目,如果在每台服务器上都启用 Memcached ,那么将会出现网站白屏、数据串站的问题,本文我们来介绍如何处理这种问题。
突破Java面试(19) - 分布式缓存的第一个问题 这个问题,互联网公司必问,要是一个人连缓存都不太清楚,那确实比较尴尬 只要问到缓存,上来第一个问题,肯定能是先问问你项目哪里用了缓存?为啥要用?不用行不行?如果用了以后可能会有什么不良的后果? 这就是看看你对你用缓存这个东西背后,有没有思考,如果你就是傻乎乎的瞎用,没法给面试官一个合理的解答。
相关文章
- Kubernetes — 我的第一个容器化应用
- Linux 典型应用之缓存服务
- wcf纯代码创建控制台应用
- 面试真题 | 什么是 Redis ? Redis缓存应用场景有哪些?
- memcached 缓存数据库应用实践
- 讲座:基于云平台进行微博应用开发
- Servlet高级应用---Servlet与缓存
- iOS 11开发教程(二十)iOS11应用视图美化按钮之设置按钮的状态
- 【快应用】推送消息token不合法案例
- 《Android 应用案例开发大全(第二版)》——6.1节Android系统的信使:Intent
- Excel 数据透视表教程大全之 02 添加字段、设置数据格式应用货币模式、按值进行排序(教程含样本数据)
- 使用Web前端技术开发桌面应用---Electron 断网提醒功能制作
- vue文档摘录二:应用 API
- 对 大数据、人工智能 等技术的现有发展及未来应用展望---------(电视节目之纪录频道视频分享)
- 浅析实际场景如何应用缓存策略:项目中什么文件用强缓存什么文件用协商缓存
- 数据库原理及MySQL应用 | 程序流程控制
- Matlab中的DSP应用中的freqs函数
- CYQ.Data V5 分布式缓存Redis应用开发及实现算法原理介绍
- Vue中应用CORS实现AJAX跨域,及它在 form data 和 request payload 的小坑处理