最近在公司项目迭代过程中,由于业务需求变更,需要做服务器负载均衡,就是需要将一个web站点布到两天服务器上,那么随之而来就会产生一个问题,代码中的全局静态可变对象变量(因为这个变量虽然是静态的,但是由于代码业务需要,需要往这个变量对象中不停的增加、修改或者删除相应属性的值)。那么就需要我们将该对象变量放到分布式缓存上进行存储,那么需求来了,我们如何动最小的代码或者说最最少的改动来实现这个需求呢。
如果按照正常逻辑,我们肯定是在该对象变量实例化、所有的设置该对象的值的地方(添加、修改和删除等)代码逻辑地方去更改迭代代码,实现由内存唯一变量到服务器缓存上存储。但是如此一来,改动量太大,如何减少代码量来实现这一个功能需求呢。
例如我们代码如下:
public static GlobalVariables Singleton { get { //注释掉的为原来的代码 //if (singleton == null) //{ // lock (locker) // { // if (singleton == null) // { // singleton = new GlobalVariables(); // } // } //} //return singleton; //直接从Redis缓存服务器读取当前实例 var entity = RedisCahingUtility.GetNewTonSoft<GlobalVariables>(global_redisConnstr); if(entity==null) { entity = new GlobalVariables(); //存储到Redis缓存 RedisCahingUtility.Put<GlobalVariables>(global_redisConnstr, entity); } tempSingleton = entity; return entity; } }
这是第一步,将一个单例的全局变量更改为从Redis缓存中读取。下面我们需要做的就是所有操作该对象的地方,我们查找引用发现,有好多引用的地方,比如add方法和remove方法:
我们可以看到有将近50个引用,这里可能需要所有add和remove的地方我们都需要去做一件事,就是add或者remove之后再同步更新到缓存服务器,如果我们一条条的去找去改,代码量就会很大。
我们可以自己自定义一个类,继承原来的Dictionary,然后重写add和remove方法:
/// <summary> /// 自定义字典 /// </summary> /// <typeparam name="TKey"></typeparam> /// <typeparam name="TValue"></typeparam> public class MyDictionary<TKey, TValue> : Dictionary<TKey, TValue> { /// <summary> /// 自定义重写add方法 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public new void Add(TKey key, TValue value) { base.Add(key, value);//调用基类方法实现原有操作 RedisCahingUtility.Put<GlobalVariables>(GlobalVariables.global_redisConnstr,GlobalVariables.tempSingleton);//同步到分布式缓存 } /// <summary> /// 自定义重写remove方法 /// </summary> /// <param name="key"></param> /// <returns></returns> public new bool Remove(TKey key) { bool r = base.Remove(key);//调用基类方法实现原有操作 RedisCahingUtility.Put<GlobalVariables>(GlobalVariables.global_redisConnstr, GlobalVariables.tempSingleton);//同步到分布式缓存 return r; }
下一步,我们只需要将字典类改成我们自定义的这个类即可:
然后其他代码都可以无需更改,因为我们自定义了一个字典类,而且重写了add和remove方法,原来所有调用的方法都能使用,而且add和remove方法也加上了我们需要的逻辑(同步分布式缓存)。