当前位置: 首页 > news >正文

庆阳市网站建设_网站建设公司_Windows Server_seo优化

江苏建设网官方网站,wordpress中文排版,全国工程招标信息网,flashfxp 网站前言在使用分布式缓存的时候#xff0c;都不可避免的要做这样一步操作#xff0c;将数据序列化后再存储到缓存中去。序列化这一操作#xff0c;或许是显式的#xff0c;或许是隐式的#xff0c;这个取决于使用的package是否有帮我们做这样一件事。本文会拿在.NET Core环境… 前言在使用分布式缓存的时候都不可避免的要做这样一步操作将数据序列化后再存储到缓存中去。序列化这一操作或许是显式的或许是隐式的这个取决于使用的package是否有帮我们做这样一件事。本文会拿在.NET Core环境下使用Redis和Memcached来当例子说明其中Redis主要是用StackExchange.RedisMemcached主要是用EnyimMemcachedCore。先来看看一些我们常用的序列化方法。常见的序列化方法或许比较常见的做法就是将一个对象序列化成byte数组然后用这个数组和缓存服务器进行交互。关于序列化业界有不少算法这些算法在某种意义上表现的结果就是速度和体积这两个问题。其实当操作分布式缓存的时候我们对这两个问题其实也是比较看重的在同等条件下序列化和反序列化的速度可以决定执行的速度是否能快一点。序列化的结果也就是我们要往内存里面塞的东西如果能让其小一点也是能节省不少宝贵的内存空间。当然本文的重点不是去比较那种序列化方法比较牛逼而是介绍怎么结合缓存去使用也顺带提一下在使用缓存时序列化可以考虑的一些点。下面来看看一些常用的序列化的库System.Runtime.Serialization.Formatters.BinaryNewtonsoft.Jsonprotobuf-netMessagePack-CSharp....在这些库中System.Runtime.Serialization.Formatters.Binary是.NET类库中本身就有的所以想在不依赖第三方的packages时这是个不错的选择。Newtonsoft.Json应该不用多说了。protobuf-net是.NET实现的Protocol Buffers。MessagePack-CSharp是极快的MessagePack序列化工具。这几种序列化的库也是笔者平时有所涉及的还有一些不熟悉的就没列出来了在开始之前我们先定义一个产品类后面相关的操作都是基于这个类来说明。public class Product{      public int Id { get; set; }    public string Name { get; set; } }下面先来看看Redis的使用。Redis在介绍序列化之前我们需要知道在StackExchange.Redis中我们要存储的数据都是以RedisValue的形式存在的。并且RedisValue是支持stringbyte[]等多种数据类型的。换句话说就是在我们使用StackExchange.Redis时存进Redis的数据需要序列化成RedisValue所支持的类型。这就是前面说的需要显式的进行序列化的操作。先来看看.NET类库提供的BinaryFormatter。序列化的操作using (var ms new MemoryStream()) {formatter.Serialize(ms, product);                db.StringSet(binaryformatter, ms.ToArray(), TimeSpan.FromMinutes(1)); }反序列化的操作var value db.StringGet(binaryformatter);using (var ms new MemoryStream(value)) {    var desValue (Product)(new BinaryFormatter().Deserialize(ms));Console.WriteLine(${desValue.Id}-{desValue.Name}); }写起来还是挺简单的但是这个时候运行代码会提示下面的错误说是我们的Product类没有标记Serializable。下面就是在Product类加上[Serializable]。再次运行已经能成功了。再来看看Newtonsoft.Json序列化的操作using (var ms new MemoryStream()) {    using (var sr new StreamWriter(ms, Encoding.UTF8))       using (var jtr new JsonTextWriter(sr)){jsonSerializer.Serialize(jtr, product);}                db.StringSet(json, ms.ToArray(), TimeSpan.FromMinutes(1)); }反序列化的操作var bytes db.StringGet(json);using (var ms new MemoryStream(bytes))using (var sr new StreamReader(ms, Encoding.UTF8))using (var jtr new JsonTextReader(sr)) {    var desValue jsonSerializer.DeserializeProduct(jtr);Console.WriteLine(${desValue.Id}-{desValue.Name}); }由于Newtonsoft.Json对我们要进行序列化的类有没有加上Serializable并没有什么强制性的要求所以去掉或保留都可以。运行起来是比较顺利的。当然也可以用下面的方式来处理的var objStr JsonConvert.SerializeObject(product); db.StringSet(json, Encoding.UTF8.GetBytes(objStr), TimeSpan.FromMinutes(1));var resStr Encoding.UTF8.GetString(db.StringGet(json));var res JsonConvert.DeserializeObjectProduct(resStr);再来看看ProtoBuf序列化的操作using (var ms new MemoryStream()) {Serializer.Serialize(ms, product);db.StringSet(protobuf, ms.ToArray(), TimeSpan.FromMinutes(1)); }反序列化的操作var value db.StringGet(protobuf);using (var ms new MemoryStream(value)) {    var desValue Serializer.DeserializeProduct(ms); Console.WriteLine(${desValue.Id}-{desValue.Name}); }用法看起来也是中规中矩。但是想这样就跑起来是没那么顺利的。错误提示如下处理方法有两个一个是在Product类和属性上面加上对应的Attribute另一个是用ProtoBuf.Meta在运行时来处理这个问题。可以参考AutoProtobuf的实现。下面用第一种方式来处理直接加上[ProtoContract]和[ProtoMember]这两个Attribute。再次运行就是我们所期望的结果了。最后来看看MessagePack据其在Github上的说明和对比似乎比其他序列化的库都强悍不少。它默认也是要像Protobuf那样加上MessagePackObject和Key这两个Attribute的。不过它也提供了一个IFormatterResolver参数可以让我们有所选择。下面用的是不需要加Attribute的方法来演示。序列化的操作var serValue MessagePackSerializer.Serialize(product, ContractlessStandardResolver.Instance); db.StringSet(messagepack, serValue, TimeSpan.FromMinutes(1));反序列化的操作var value db.StringGet(messagepack);var desValue MessagePackSerializer.DeserializeProduct(value, ContractlessStandardResolver.Instance);此时运行起来也是正常的。其实序列化这一步对Redis来说是十分简单的因为它显式的让我们去处理然后把结果进行存储。上面演示的4种方法从使用上看似乎都差不多没有太大的区别。如果拿Redis和Memcached对比会发现Memcached的操作可能比Redis的略微复杂了一点。下面来看看Memcached的使用。MemcachedEnyimMemcachedCore默认有一个 DefaultTranscoder对于常规的数据类型(int,string等)本文不细说只是特别说明object类型。在DefaultTranscoder中对Object类型的数据进行序列化是基于Bson的。还有一个BinaryFormatterTranscoder是属于默认的另一个实现这个就是基于我们前面的说.NET类库自带的System.Runtime.Serialization.Formatters.Binary。先来看看这两种自带的Transcoder要怎么用。先定义好初始化Memcached相关的方法以及读写缓存的方法。初始化Memcached如下private static void InitMemcached(string transcoder ){IServiceCollection services new ServiceCollection();services.AddEnyimMemcached(options {options.AddServer(127.0.0.1, 11211);options.Transcoder transcoder;});services.AddLogging();IServiceProvider serviceProvider services.BuildServiceProvider();_client serviceProvider.GetServiceIMemcachedClient() as MemcachedClient; }这里的transcoder就是我们要选择那种序列化方法(针对object类型)如果是空就用Bson如果是BinaryFormatterTranscoder用的就是BinaryFormatter。需要注意下面两个说明2.1.0版本之后Transcoder由ITranscoder类型变更为string类型。2.1.0.5版本之后可以通过依赖注入的形式来完成而不用指定string类型的Transcoder。读写缓存的操作如下private static void MemcachedTrancode(Product product){_client.Store(Enyim.Caching.Memcached.StoreMode.Set, defalut, product, DateTime.Now.AddMinutes(1));Console.WriteLine(serialize succeed!);    var desValue _client.ExecuteGetProduct(defalut).Value;Console.WriteLine(${desValue.Id}-{desValue.Name});Console.WriteLine(deserialize succeed!); }我们在Main方法中的代码如下 static void Main(string[] args){Product product new Product{Id 999,Name Product999};    //Bsonstring transcoder ;    //BinaryFormatter//string transcoder BinaryFormatterTranscoder;            InitMemcached(transcoder);MemcachedTrancode(product);Console.ReadKey(); }对于自带的两种Transcoder跑起来还是比较顺利的在用BinaryFormatterTranscoder时记得给Product类加上[Serializable]就好下面来看看如何借助MessagePack来实现Memcached的Transcoder。这里继承DefaultTranscoder就可以了然后重写SerializeObjectDeserializeObject和Deserialize这三个方法。public class MessagePackTranscoder : DefaultTranscoder{    protected override ArraySegmentbyte SerializeObject(object value)    {        return MessagePackSerializer.SerializeUnsafe(value, TypelessContractlessStandardResolver.Instance);}      public override T DeserializeT(CacheItem item){         return (T)base.Deserialize(item);}      protected override object DeserializeObject(ArraySegmentbyte value)    {        return MessagePackSerializer.Deserializeobject(value, TypelessContractlessStandardResolver.Instance);} }庆幸的是MessagePack有方法可以让我们直接把一个object序列化成ArraySegment也可以把ArraySegment 反序列化成一个object相比Json和Protobuf省去了不少操作这个时候我们有两种方式来使用这个新定义的MessagePackTranscoder。方式一 在使用的时候我们只需要替换前面定义的transcoder变量即可(适用2.1.0版本)。string transcoder CachingSerializer.MessagePackTranscoder,CachingSerializer;注如果使用方式一来处理记得将transcoder的拼写不要错并且要带上命名空间不然创建的Transcoder会一直是null从而走的就是Bson了! 本质是 Activator.CreateInstance应该不用多解释。方式二通过依赖注入的方式来处理(适用2.1.0.5版本)private static void InitMemcached(string transcoder ){IServiceCollection services new ServiceCollection();services.AddEnyimMemcached(options {options.AddServer(127.0.0.1, 11211);        //这里保持空字符串或不赋值就会走下面的AddSingleton//如果这里赋了正确的值后面的AddSingleton就不会起作用了options.Transcoder transcoder;});    //使用新定义的MessagePackTranscoderservices.AddSingletonITranscoder, MessagePackTranscoder();    //others...}运行之前加个断点确保真的进了我们重写的方法中。最后的结果Protobuf和Json的在这里就不一一介绍了这两个处理起来比MessagePack复杂了不少。可以参考MemcachedTranscoder这个开源项目也是MessagePack作者写的虽然是5年前的但是一样的好用。对于Redis来说在调用Set方法时要显式的将我们的值先进行序列化不那么简洁所以都会进行一次封装在使用。对于Memcached来说在调用Set方法的时候虽然不需要显式的进行序列化但是有可能要我们自己去实现一个Transcoder这也是有点麻烦的。下面给大家推荐一个简单的缓存库来处理这些问题。使用EasyCaching来简化操作EasyCaching是笔者在业余时间写的一个简单的开源项目主要目的是想简化缓存的操作目前也在不断的完善中。EasyCaching提供了前面所说的4种序列化方法可供选择BinaryFormatterMessagePackJsonProtoBuf如果这4种都不满足需求也可以自己写一个只要实现IEasyCachingSerializer这个接口相应的方法即可。Redis在介绍怎么用序列化之前先来简单看看是怎么用的(用ASP.NET Core Web API做演示)。添加Redis相关的nuget包Install-Package EasyCaching.Redis修改Startuppublic class Startup{    //...public void ConfigureServices(IServiceCollection services)    {        //other services.//Important step for Redis Caching       services.AddDefaultRedisCache(option{                option.Endpoints.Add(new ServerEndPoint(127.0.0.1, 6379));option.Password ;});} }然后在控制器中使用[Route(api/[controller])]public class ValuesController : Controller{    private readonly IEasyCachingProvider _provider;    public ValuesController(IEasyCachingProvider provider)    {        this._provider provider;}[HttpGet]         public string Get()    {        //Set_provider.Set(demo, 123, TimeSpan.FromMinutes(1));        //Get without data retrievervar res _provider.Getstring(demo);_provider.Set(product:1, new Product { Id 1, Name name}, TimeSpan.FromMinutes(1))        var product _provider.GetProduct(product:1);          return  ${res.Value}-{product.Value.Id}-{product.Value.Name};  } }使用的时候在构造函数对IEasyCachingProvider进行依赖注入即可。Redis默认用了BinaryFormatter来进行序列化。下面我们要如何去替换我们想要的新的序列化方法呢以MessagePack为例先通过nuget安装packageInstall-Package EasyCaching.Serialization.MessagePack然后只需要在ConfigureServices方法中加上下面这句就可以了。public void ConfigureServices(IServiceCollection services){    //others..services.AddDefaultMessagePackSerializer(); }Memcached同样先来简单看看是怎么用的(用ASP.NET Core Web API做演示)。添加Memcached的nuget包Install-Package EasyCaching.Memcached修改Startuppublic class Startup{    //...public void ConfigureServices(IServiceCollection services)    {services.AddMvc();        //Important step for Memcached Cacheservices.AddDefaultMemcached(option{                option.AddServer(127.0.0.1,11211);            });        }        public void Configure(IApplicationBuilder app, IHostingEnvironment env)    {        //Important step for Memcache Cacheapp.UseDefaultMemcached();    } }在控制器中使用时和Redis是一模一样的。这里需要注意的是在EasyCaching中默认使用的序列化方法并不是DefaultTranscoder中的Bson而是BinaryFormatter如何去替换默认的序列化操作呢同样以MessagePack为例先通过nuget安装packageInstall-Package EasyCaching.Serialization.MessagePack剩下的操作和Redis是一样的public void ConfigureServices(IServiceCollection services){    //others..services.AddDefaultMemcached(op{                op.AddServer(127.0.0.1,11211);});    //specify the Transcoder use messagepack serializer.services.AddDefaultMessagePackSerializer(); }因为在EasyCaching中有一个自己的Transcoder这个Transcoder对IEasyCachingSerializer进行注入所以只需要指定对应的Serializer即可。总结一、 先来看看文中提到的4种序列化的库System.Runtime.Serialization.Formatters.Binary在使用上需要加上[Serializable]效率是最慢的优势就是类库里面就有不需要额外引用其他package。Newtonsoft.Json使用起来比较友善可能是用的多的缘故也不需要我们对已经定义好的类加一些Attribute上去。protobuf-net使用起来可能就略微麻烦一点可以在定义类的时候加上相应的Attribute也可以在运行时去处理(要注意处理子类)不过它的口碑还是不错的。MessagePack-CSharp虽然可以不添加Attribute但是不加比加的时候也会有所损耗。至于如何选择可能就要视情况而定了有兴趣的可以用BenchmarkDotNet跑跑分我也简单写了一个可供参考SerializerBenchmark二、在对缓存操作的时候可能会更倾向于“隐式”操作能直接将一个object扔进去也可以直接将一个object拿出来至少能方便使用方。三、序列化操作时Redis要比Memcached简单一些。最后如果您在使用EasyCaching有问题或建议可以联系我前半部分的示例代码CachingSerializer后半部分的示例代码sample原文https://www.cnblogs.com/catcher1994/p/8543711.html.NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com
http://www.ihoyoo.com/news/46646.html

相关文章:

  • 网站加入百度地图网站开发使用哪些开发语言
  • 青岛旅游网站建设类似于wordpress的
  • 铁门关网站建设重庆工商局官网
  • 建设足球网站的心得和意义浦东新区建设工程安全质量监督站网站
  • 百度做网站推广网站信息架构
  • 怎么做公司的网站做企业官网的流程
  • 农业科技公司网站模板科技公司网站系统
  • 大气公司网站源码游戏加盟网
  • 建站网站免费wordpress 轻论坛
  • 商会网站建设开发上海网站建设的价格
  • 安徽建站管理系统价格wordpress文章分页共多少页
  • H5响应式网站数据潍坊做网站张家口
  • 网站建设科技风eroticalia wordpress
  • 空间有了怎么做网站中国定制家具网
  • 相亲网站怎么做的网站交易截图可以做证据吗
  • html5购物网站wordpress分类多重筛选
  • 河北省建设集团有限公司网站php网站模板源码下载
  • 徐州做网站谁家最专业找别人做淘客网站他能改pid吗
  • 马鞍山网站建设咨询电代理办公司注册大概多少钱
  • 网站流量统计工具网站建设与网页制作实训报告
  • 网站开发平台选择ip地址免费
  • 替别人做网站管理员甘肃百度推广电话
  • 网站搭建报价表义乌开锁做网站哪个好
  • 网站建站网站建站重庆seo论
  • 机票便宜网站建设做阿里云网站空间
  • 网站被百度降权了怎么办雄安移动网站建设
  • 网站设计 导航条营销策划方案步骤
  • 如何做好电子商务网站开发企业网站网络营销
  • 网站备案中国开头wordpress获取当前分类
  • 网站关键字被百度收录wordpress添加追番