• 分布式缓存: Velocity之高级应用


    概述

    Velocity是微软推出的分布式缓存解决方案,为开发可扩展性,可用的,高性能的应用程提供支持,可以缓存各种类型的数据,如CLR对象、XML、二进制数据等,并且支持集群模式的缓存服务器。Velocity也将集成在.NET Framework 4.0中,本文将介绍Velocity中的悲观锁定,缓存项版本、日志记录、客户端缓存以及路由表等知识。

    悲观锁定

    Velocity提供了一套悲观锁定模型,即在某个缓存项数据处理过程中,数据将处于锁定状态,来自于其它客户端应用程序将无法对该缓存项进行处理。提供悲观锁定的方法主要三个,如下代码所示:

    GetAndLock():获取缓存项并对数据加锁;

    PutAndUnlock():更新加锁的数据并释放锁;

    Unlock():释放锁定。

    先来看GetAndLock()方法,在获取缓存项时并加锁,此时如果其它客户端试图获取该数据并加锁(即调用GetAndLock方法)将会失败,而不会阻塞;但客户端如果只想获取数据(即调用Get方法),则会返回相应数据,可以用图1形象的来表示:

    1

    可以看到,ClientA获取数据成功并加锁;ClientB再次想获取数据并加锁时,将会失败;ClientC能够获取数据。

    使用GetAndLock()方式可以指定锁过期时间,并且会有输出参数LockHandle,该参数将会在PutAndUnlock()方法或Unlock()中来释放锁,如下代码所示:

    Cache cache = GetCurrentCache();

    LockHandle handle = new LockHandle();

    Customer item = (Customer)cache.GetAndLock("C20081117005",

    new TimeSpan(0, 30, 0), out handle);

     

    Customer customer = new Customer()

    {

    ID = "C20081117005",

    FirstName = "Terry",

    LastName = "Lee",

    Age = 25,

    Email = "lhj_cauc[#AT#]163.com"

    };

    cache.PutAndUnlock(customer.ID, customer, handle, null);

    日志记录

    Velocity中同样提供了日志记录的功能,我们可以在应用程序配置文件中进行设置,它支持基于控制台、基于文件以及Windows事件跟踪三种方式的记录,在配置文件中首先添加配置区:

    <section name="fabric" type="System.Data.Fabric.Common.ConfigFile, FabricCommon"

    allowLocation="true" allowDefinition="Everywhere"/>

    然后可以进行配置,如设置日志记录级别等:

    <fabric>

    <section name="logging" path="">

    <collection name="sinks" collectionType="list">

    <customType className="System.Data.Fabric.Common.EventLogger,FabricCommon"

    sinkName="System.Data.Fabric.Common.ConsoleSink,FabricCommon"

    sinkParam="" defaultLevel="-1"/>

    <customType className="System.Data.Fabric.Common.EventLogger,FabricCommon"

    sinkName="System.Data.Fabric.Common.FileEventSink,FabricCommon"

    sinkParam="CacheClientLog" defaultLevel="1"/>

    <customType className="System.Data.Fabric.Common.EventLogger,FabricCommon"

    sinkName="System.Data.Caching.ETWSink, CacheBaseLibrary"

    sinkParam="" defaultLevel="-1" />

    </collection>

    </section>

    </fabric>

    同样也可以在代码中设置,调用CacheFactory的两个静态方法CreateLogSinksDisableLogSinks,如下代码所示:

    private Cache GetCurrentCache()

    {

    List<LogSink> sinklist = new List<LogSink>(2);

    LogSink fileBasedSink = new LogSink(SinkType.FILE,

    TraceLevel.Warning, "DCache/dd-hh-mm");

    LogSink consoleBasedSink = new LogSink(SinkType.CONSOLE,

    TraceLevel.Warning);

    sinklist.Add(fileBasedSink);

    sinklist.Add(consoleBasedSink);

    // 启用

    CacheFactory.CreateLogSinks(sinklist);

     

    // 禁用

    CacheFactory.DisableLogSinks();

     

    Cache dCache;

    ServerEndPoint[] servers = new ServerEndPoint[1];

    servers[0] = new ServerEndPoint("localhost", 22233, "DistributedCacheService");

    bool routingClient = true;

    bool localCache = false;

     

    var factory = new CacheFactory(servers, routingClient, localCache);

    dCache = factory.GetCache("default");

     

    return dCache;

    }

    缓存项版本

    Velocity中提供了一种基于版本的更新功能,当使用GetCacheItem()方法时将返回一个缓存项,并携带有版本信息,当每次对缓存项做更新时,在内部都会对它的版本增加。如下面的示例,有两个客户应用程序,它们同时获取了同一个缓存项:

    ClientA

    CacheItem item = cache.GetCacheItem("Customers", "C2008");

    ClientB

    CacheItem item = cache.GetCacheItem("Customers", "C2008");

    并且同时对缓存项做修改:

    ClientA

    ((Customer)item.CacheObject).FirstName = "Huijun";

    ClientB

    ((Customer)item.CacheObject).FirstName = "Terry";

    如果ClientA首先提交更改,在提交更改时携带版本信息,由于版本信息与内部的版本一致,所以提交成功:

    ClientA

    cache.Put("Customers", "C2008", item.CacheObject, item.Version);

    此时内部版本将会增加,现在ClientB如果再提交更改,将会失败,因为版本无法匹配,如图2表示:

    2

    客户端缓存

    Velocity中还支持客户端缓存,如果启用了客户端缓存后,在从缓存集群中取回数据时,将会放在客户端缓存中,这样下次取数据时将会直接从客户端缓存中取出,能够极大的提高效率,有点像是缓存的缓存。当集群中的数据发生变化时,Velocity将会使用事件通知机制通知客户端缓存刷新数据,如图3所示:

    3

    要启用客户端缓存,一是使用配置文件,设置IsEnabled属性为True,如下代码所示:

    <dcacheClient deployment="routing">

    <localCache isEnabled="true" sync="TTLBased" ttlValue="300" />

    <hosts>

    <host name="localhost" cachePort="22233"

    cacheHostName="DistributedCacheService"/>

    </hosts>

    </dcacheClient>

    直接指定启用客户端缓存即可,另外也可以在创建CacheFactory时指定,如下代码所示:

    Cache dCache;

    ServerEndPoint[] servers = new ServerEndPoint[1];

    servers[0] = new ServerEndPoint("localhost", 22233, "DistributedCacheService");

    bool routingClient = true;

    bool localCache = false;

     

    var factory = new CacheFactory(servers, routingClient, localCache);

    dCache = factory.GetCache("default");

     

    return dCache;

    路由客户端

    Velocity中在缓存客户端,提供了一种路由客户端Routing Client,它能够提供比简单客户端Simple Client更好的性能,在Routing Client中会有一个路由表Routing Table,它用来跟踪缓存对象,它是全局缓存中的分区映射的一个子集,同时分发缓存操作(PutGet等)到确定的缓存宿主。路由客户端使用此路由表来优化性能,因为该表可以跟踪缓存对象,所以当有请求到缓存宿主时,可以进行物理上的定位。如图4所示:

    4

    是否在应用程序中启用路由客户端,可以由开发者来确定,如在配置中启用路由客户端,这里可以通过指示deployment来设定是路由客户端(routing)还是简单客户端(simple):

    <dcacheClient deployment="routing">

    <localCache isEnabled="true" sync="TTLBased" ttlValue="300" />

    <hosts>

    <host name="localhost" cachePort="22233"

    cacheHostName="DistributedCacheService"/>

    </hosts>

    </dcacheClient>

    另外还可以通过代码来设置,如下面的代码,在创建CacheFactory时指定构造函数参数:

    Cache dCache;

    ServerEndPoint[] servers = new ServerEndPoint[1];

    servers[0] = new ServerEndPoint("localhost", 22233, "DistributedCacheService");

    bool routingClient = true;

    bool localCache = false;

     

    var factory = new CacheFactory(servers, routingClient, localCache);

    dCache = factory.GetCache("default");

     

    return dCache;

    Velocity组成

    最后我们再看一幅图,来了解一下Velocity的组成部分,可以看到它可以分为客户端缓存、服务端缓存以及管理工具三部分,如图5所示:

    5

    总结

    本文介绍了Velocity中的悲观锁定,缓存项版本、日志记录、客户端缓存以及路由表等知识,希望对大家有用。至此,关于微软的分布式缓存服务Velocity就用短短的三篇文章介绍到这里,期待在.NET Framework 4.0Velocity能够为我们带来更多的惊喜。

  • 相关阅读:
    Codeforces Round #297 (Div. 2)D. Arthur and Walls 暴力搜索
    Codeforces Round #297 (Div. 2)C. Ilya and Sticks 贪心
    Codeforces Round #297 (Div. 2)B. Pasha and String 前缀和
    Codeforces Round #297 (Div. 2)A. Vitaliy and Pie 水题
    BZOJ 1191: [HNOI2006]超级英雄Hero 匈牙利算法
    Codeforces Round VK Cup 2015
    Codeforces Round #296 (Div. 1) C. Data Center Drama 欧拉回路
    BZOJ 1059: [ZJOI2007]矩阵游戏 匈牙利算法
    UOJ #17. 【NOIP2014】飞扬的小鸟 背包DP
    Hibernate自定义字段查询
  • 原文地址:https://www.cnblogs.com/Alum/p/3600051.html
Copyright © 2020-2023  润新知