Cache module Design

Source: Internet
Author: User

NET Cache Module Design

The previous article talked about my concept of caching, the framework of understanding and views, this article to take up my own cache module design practice.

Basic Cache Module Design

The most basic cache module must have a unified cachehelper, as follows:

    Public interface Icachehelper    {              T get<t> (string key);                       void set<t> (String key, T value);               void Remove (string key);                   

Then the business layer is called in this way

        Public User Get (int id)        {            if (id <= 0)                throw new ArgumentNullException ("id");            var key = string. Format (User_cache_key, id);            var user = _cachehelper.get<user> (key);            if (user! = null)                return user;            Return _repository. Get (ID);        }    

There is nothing wrong with the code above, but the actual use of it is problematic, because I have always stressed that the cache to save "hot data", so that "hot data" must have expired, we can not write another to set. So it is more appropriate to combine the writing together.

Public User GetV2 (int id) {    if (id <= 0)       throw new ArgumentNullException ("id");    var key = string. Format (User_cache_key, id);    var user = _cachehelper.get<user> (key);    if (user! = null)       return user;    
user = _repository. Get (ID); if (user! = null) _cachehelper.set (key, user);
return user;}

The above code is just adding a set, so the design, each time a get need to repeat the code is too much, then should be more streamlined? This time to eat some C # syntax sugar is necessary, grammar sugar occasionally eat a little to improve efficiency, why not?

Public User GetV3 (int id) {      if (id <= 0)          throw new ArgumentNullException ("id");      var key = string. Format (User_cache_key, id);       Return _cachehelperv2.get<user> (key, () = _repository. Get (ID));            } ICache get<t> implements public T get<t> (string key, func<t> fetch = null) {    t result = default (t);    var obj = cache.get (key);    if (obj is T)    {        result = (t) obj;    }    if (result = = null)    {        result = Fetch ();        if (result! = null)            Set (key, result);    }    return result;}            

Here I have directly packed the set method into the Icache.get<t>, with fetch Func attached. This abstracted the public operations together, simplifying the call of the cache, which perfectly fits my mind.

Advanced Cache Module Design

The Icache V3 in the previous section was almost the most streamlined, but in fact, after referring to Servicestack.redis, I discovered a more abstract approach. Obviously all the code in the previous section is manually managed key, and for the usual object cache, does this key need to be manually? to the last improvement.

Public T get<t> (object ID, func<t> fetch = null) {    var type = typeof (T);    var key = string. Format ("urn:{1}:{2}", type. Name, ID. ToString ());//Here is the key, directly using TypeName to act as key    return Get (key, fetch);} Public T get<t> (string key, func<t> fetch = null) {    t result = default (t);    var obj = cache.get (key);    if (obj is T)    {        result = (t) obj;    }    if (result = = null)    {        result = Fetch ();        if (result! = null)           Set (key, result);     }     return result;}

The Get method completely automates the management of key and then calls the way it is streamlined again.

Public User GetV4 (int id) {     if (id <= 0)        throw new ArgumentNullException ("id");     return _cachehelperv3.get<user> (ID, () = _repository. Get (ID));}

It's obvious that the most important set, the set, this key acquisition is going to cost a little bit, the most need to solve is how to get the value of the primary key ID.

public class user{        [PrimaryKey]//This attribute is the most important thing public        int UserId {get; set;}        public string UserName {get; set;}        public string Cellphone {get; set;}} public void set<t> (T obj) {      ///here should be cached to increase the efficiency of the reflection      var type = typeof (T);      var PrimaryKey = type. GetProperties ()                . FirstOrDefault (t = = T.getcustomattributes (false)                    . Any (c + + C is primarykeyattribute));//This is done by taking Primarykeyattribute to get the ID of value       var keyValue = Primarykey.getvalue ( obj, null);                   var key = string. Format ("Urn:{0}:{1}", type. Name, keyValue);       var dt = DateTime.UtcNow.AddDays (1);//assume default cache of 1 days        var = new DateTimeOffset (DT);        Cache.set (key, obj, offset);}

Here I think the final version of Icache is complete. It also needs to be explained that the PrimaryKey can be more flexible and changeable. Many times a primarykey of an object is very complex, and this time the cache entity can be designed with the following modifications:

public class usercacheentity{        [PrimaryKey] public        int ID        {            get            {                return string. Format ("{0}:{1}", UserId, UserName);            }        }        public int UserId {get; set;}        public string UserName {get; set;}        public string Cellphone {get; set;}}

The above method can almost automatically manage the common data cache, the only trouble is the need to customize a cacheobject, which brings the problem of entity conversion, it is necessary to see how to choose.

Again, I want the Icache design:

1. Always cache hot data, which means that each key has an expiration time

2. Icache Automatic management of Get/set, it is best to automatically manage key.

3. Icache streamlining without losing flexibility.

The detailed code demo can refer to: Git

More flexible implementations

Before I write this summary, I have been thinking about what layer the cache should be placed on and where to put it on the three floor. Where do you put your ddd when it's layered? Google, see a few references.

Http://stackoverflow.com/questions/15340173/in-which-layer-implement-the-cache

I think this is more in line with my idea, the cache should be global arbitrary, of course, the implementation of course is INTERFACE+IOC, so the reference is more independent.

In addition to the more advanced use of the cache, AOP combined with Icache V4 such a design, wouldn't it be better? Here I have not to realize the attribute of AOP, this is another big topic, next time come to realize it.

Cache module Design

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.