首页 > 代码库 > 实现一个基于WCF的分布式缓存系统

实现一个基于WCF的分布式缓存系统

前言:

用到分布式的东西很多了,一直想做一个简单的分布式小项目练练手学习下。后来决定来一个简单的分布式缓存的系统。

在企业应用开发中缓存的用例不胜枚举,但是每次更多的是单机的部署与使用,没有对应的需求是一个原因,另一个原因总是好高骛远做过的总是不想再进行修正。

这次的分布式就从最简单的分布式缓存开始。说简单是因为没有实现分布式缓存高深的寻址,或者对备份处理的牛X实现。只是实现了“分布”这个目的,不足之处还请大家指导。

分布的实现方式有哪些?

既然做“分布”,当然要看看主流的“分布”实现方式。小弟简单的在网上搜罗了一下,常见的方式有两种(或者说是最简单的):

  1. 交由客户端分布;
  2. 交由服务端分布;

 

针对于第一种,最显而易见的是MM的实现,如:

string[] serverlist = { "10.0.0.131:11211", "10.0.0.132:11211" }; MemcachedClient mc = new MemcachedClient(); mc.Set("test", "my value");

这3行代码是我们再使用MM时候常用的,可以把值放在指定的集群上。

 

针对于第二种,交由服务端又可以分为两种实现:

  1. 主目标服务器维护着一个Cache集群,每当主Server接收到一个缓存请求时,则通知集群机器进行缓存。
  2. 第二种类似于上一条的实现,只不过是交由一个后台线程去做通知工作。

 

两种很类似,但是要想达到最优的效果应该需要一个强有力的算法去支撑了。

 

制定策略

既然分析了这两种实现的方式,个人更喜欢第二种中的第一种,起码在角色上更加的清晰。

虽然图画的有点惨,但是大致说明了问题,就是Client通知ServerHost缓存,ServerHost帮助分布式,当Client请求缓存值时,Serverhost则呼叫离Client最近的Host返回cache值。

但是考虑到万一ServerHost挂掉了,真个系统是不是就瘫痪了,于是修改方案:

也就没有了ServerHost每一个Host都起到了ServerHost的功效。

 

代码实现:

每个Host是一个控制台作为Wcf的host,当然最好的情况应该是使用WindowsServer:

class Program    {        static void Main(string[] args)        {            ServiceHost host = new ServiceHost(typeof(DistributedCache.Services.NetCacheService));            try            {                host.Open();                Console.WriteLine("NetCacheService Service Started");                Console.ReadKey();            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);                if (ex.InnerException != null)                {                    Console.WriteLine("\n" + ex.InnerException.Message);                }            }            finally            {                host.Close();            }            Console.ReadKey();        }    }

在CacheService上提供的简单API:

    [ServiceContract]    public interface INetCacheService    {        [OperationContract]        String AppendCache(String key, Object value);        [OperationContract]        String RemoveCache(String key);        [OperationContract]        String ClearCache();        [OperationContract]        Object GetCache(String key);    }

每一个Client对应着自己的Host:

        static void Main(string[] args)        {            DistributedCacheService.INetCacheService service = new DistributedCacheService.NetCacheServiceClient();            string value = http://www.mamicode.com/"test string";            service.AppendCache("zhazha", value);            System.Console.WriteLine("set ‘zhazha‘ value : [{0}] to {1} succeed!", value, "172.16.15.121");            System.Console.Read();        }

为了达到动态管理分布Server的目的:

首先两个IP的集群:

  <appSettings>    <add key="hostIP" value=http://www.mamicode.com/"172.16.15.121:9876,172.16.15.205:9876"/>  </appSettings>

缓存集群的同步:

                HttpRuntime.Cache.Insert(key, value, null, DateTime.UtcNow.AddMinutes(EXPIRETIME), TimeSpan.Zero);                System.Console.WriteLine("{0} : localhost write cache succeed!", DateTime.Now.ToString());                string[] hostIP = ChannelFactory.GetHost();                object obj = null;                CacheService02.INetCacheService service = null;                for (int i = 0; i < hostIP.Length; i++)                {                    service = ChannelFactory.CreateWCFServiceByURI<CacheService02.INetCacheService>(hostIP[i]);                    obj = service.GetCache(key);                    if (null == obj)                    {                        service.AppendCache(key, value);                        System.Console.WriteLine("{0} : {1} write cache succeed!", DateTime.Now.ToString(), hostIP[i]);                    }                }                System.Console.WriteLine("{0} : write cache succeed!", DateTime.Now.ToString());                return "Success";

测试结果:

我们验证了从121机器上请求缓存,然后121的Host挂掉了,仍旧可以通过集群中的205拿到对应的缓存值。

结语:

虽然整个一套实现的很简陋,但是基本达到了一个“分布”的效果,想了下如果需要优化的地方:

  1. 可以讲缓存操作的API更加丰富些;
  2. 通过跨平台的技术(如:node)实现Host跨平台;
  3. 客户端对于Host的使用应该更加的简洁;
  4. 等等;

File path: https://github.com/zhangcj/NetCache