翼度科技»论坛 编程开发 .net 查看内容

dotnet 缓存

12

主题

12

帖子

36

积分

新手上路

Rank: 1

积分
36
Net 内置内存缓存

asp.net 中是有缓存的实现:HttpContext.Cache,缓存的数据是放到 Web 服务器的进程 内存里。
在控制台、WinForm、子线程、SignalR 等不支持 HttpContext 的地方还可以使用 MemoryCache.Default(System.Runtime.Caching 这个程序集中) ,HttpContext.Cache 其实就是 对 MemoryCache 的封装。
  1. //写入:
  2. MemoryCache.Default.Add("age", 666, DateTimeOffset.Now.AddMinutes(1));
  3. //读取:
  4. if(MemoryCache.Default.Contains("name"))
  5. {  
  6.     int age = (int)MemoryCache.Default["age"];               
  7. }
复制代码
进程内缓存最大的优点就是效率高。在可预期数据量不大的情况下推荐使用。 如果数据量比较大或者集群服务器比较多,就要用单独的分布式缓存了,也就是搞一台 或者多台专门服务器保存缓存数据,所有服务器都访问分布式缓存服务器。
Memcached

简介

Memcached 是一个专门用来做缓存的服务器,而且缓存的数据都在内存中。Memcached 就相当于一个 Dictionary 键值对集合,保存的是键值对,然后根据 key 取 value。 当然 web 服务器和 Memcached 之间还是要网络间通讯,效率还是没有进程内缓存效率 高。Memcached 程序重启之后数据就会消失。
安装
  1. memcached.exe -d install
复制代码
卸载
  1. memcached.exe -d uninstall
复制代码
.Net 连接 memcached 安装

Memcached 的.Net 开发包:Install-Package EnyimMemcached

  • Memcache 存入的是键值对。Memcache 存入数据的 3 中模式 Set、Replace、Add,根据名 字就能猜出来:


  • Set:存在则覆盖,不存在则新增
  • Replace:如果存在则覆盖,并且返回 true;如果不存在则不处理,并且返回 false;
  • Add:如果不存在则新增,并且返回 true;如果存在则不处理,并且返回 false;
没特殊要求一般用 Set 就可以了。
  1. MemcachedClientConfiguration mcConfig = new MemcachedClientConfiguration(); mcConfig.AddServer("127.0.0.1:11211");
  2. //必须指定端口
  3. using (MemcachedClient client = new MemcachedClient(mcConfig))
  4. {  
  5.     client.Store(Enyim.Caching.Memcached.StoreMode.Set, "name", "rsfy");
  6. }
复制代码
如果保存普通类对象,则对象必须可序列化(不同 Memcached 客户端保存对象的机制 都不尽相同)。
2)存入设置过期时间 设置最后一个 TimeSpan 类型的参数:
  1. client.Store(Enyim.Caching.Memcached.StoreMode.Set, "name", "yzk",TimeSpan.FromSeconds(5));
复制代码
如果之前对于同一个 Key 设置过一个过期时间,之后又设置过一个,以最后一次的为准。
3)读取:如果找不到,则返回 null。
  1. client.Get("name");
复制代码
当然也可以用
  1. public bool TryGet(string key, out object value)
复制代码
当然还支持泛型的
  1. public T Get<T>(string key)
复制代码

  • Remove(string key)则是删除一个 key 对应的内容。  Key 的长度最高是 250 个字符,Value 最长 1M。  与 Store、Get、Remove 配套的还有 ExecuteXXX 方法,唯一区别就是返回值信息更详细。
5)Key 的选择:  Memcaced就相当于一个大键值对,不同系统放到Memcached中的数据都是不隔离的, 因此设定 Key 的时候要选择好 Key,这样就不容易冲突。建议规则“系统名字_模块名字_业务_Key”,比如“Shop_Admin_FilterWords”
6) Increment、Decrement 是用来对计数器进行增减的,不过用得少。用 Redis 更合适。
Cas 操作:

用来解决并发问题:读出一个值,做一些判断或者处理,再写回,有可能有并发的问题。 Cas 是 Memcached 1.2.5 之后引入的特性,类似于数据库的“乐观锁”,查询的时候查出一个 cas 值,在写入的时候带着这个 cas 值,如果发现 cas 值已经变了,则说明已经有别人改过了。 下面的程序:
  1. var cas = client.GetWithCas("Name");
  2. Console.WriteLine("按任意键继续");
  3. Console.ReadKey();
  4. var res = client.Cas(Enyim.Caching.Memcached.StoreMode.Set, "Name", cas.Result + "1", cas.Cas);
  5. if(res.Result) {  
  6.     Console.WriteLine("修改成功");
  7. } else {  
  8.     Console.WriteLine("被别人改了");
  9. }  
复制代码
启动两个实例,测试效果。  Memcached 一般就是做缓存用,因此也不要用这个 Cas。
memcached 的集群

memcached 重启之后短时间内大量的请求会涌入数据库,给数据库造成压力,解决这 个的方法就是使用集群,有多台 Memcached 服务器提供服务。 当 memcached 服务器压力大了之后也有必要搞 memcached 集群来分担压力。 Memcached 服务器的“雪崩”问题:如果所有缓存设置过期时间一样,那么每隔一段 时间就会造成一次数据库访问的高峰:
**解决的方法就是缓存时间设置不一样,比如加上一个随机数。 **
Memcached 的集群实现很简单,集群节点直接不进行通讯、同步,只要在多个服务器 上启动多个 Memcached 服务器即可,客户端决定把数据写入不同的实例,不搞主从复制, 每个数据库实例保存一部分内容。 然后 mcConfig.AddServer("127.0.0.1:11211");添加多个服务器 ip 地址,然后客户端根据 自己的算法决定把数据写入哪个 Memcached 实例,取数据库的时候再根据同样的定位算法 去哪台服务器上去取。 节点定位算法有很多种,最常用的有两种 Ketama、VBucket。Ketama 是根据 Key 算出一 个 hash 值,根据 hash 值再算到服务器;而 VBucket 也是根据 key 算出 hash 值,但是不是直 接根据 hash 值算出服务地址,而是维护一个 VBucket 表,在表中指定不同的 hash 值由不同 的服务器处理,还可以临时改变指向。建议用 Ketama 就可以了。节点定位算法会自动处理 故障服务器。
  1. mcConfig.NodeLocatorFactory = new KetamaNodeLocatorFactory()。
复制代码
缓存要求都 不高。
Memcached 封装示例
  1. /// <summary>
  2. /// 获取token
  3. /// </summary>
  4. /// <param name="args"></param>
  5. /// <returns>token</returns>
  6. /// <exception cref="ArgumentException"></exception>
  7. public static string JwtEncoding(Dictionary<string, object> args)
  8. {
  9.     var payload = args.Count == 0 ? throw new ArgumentException($"{nameof(args)}长度为0") : args;
  10.     var secret = ConfigurationManager.AppSettings["Jwt"];
  11.     IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
  12.     IJsonSerializer serializer = new JsonNetSerializer();
  13.     IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
  14.     IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
  15.     var token = encoder.Encode(payload, secret);
  16.     return token;
  17. }
  18. /// <summary>
  19. /// 解token
  20. /// </summary>
  21. /// <param name="token">token</param>
  22. /// <returns></returns>
  23. public static Dictionary<string, object> JwtDecoding(string token)
  24. {
  25.     Dictionary<string, object> data = null;
  26.     try
  27.     {
  28.         var secret = ConfigurationManager.AppSettings["Jwt"];
  29.         var serializer = new JsonNetSerializer();
  30.         var algorithm = new HMACSHA256Algorithm();
  31.         IDateTimeProvider provider = new UtcDateTimeProvider();
  32.         IJwtValidator validator = new JwtValidator(serializer, provider);
  33.         var urlEncoder = new JwtBase64UrlEncoder();
  34.         IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);
  35.         var json = decoder.Decode(token, secret, verify: true);
  36.         data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
  37.     }
  38.     catch (TokenExpiredException)
  39.     {
  40.         Console.WriteLine("Token has expired");
  41.         return null;
  42.     }
  43.     catch (SignatureVerificationException)
  44.     {
  45.         Console.WriteLine("Token has invalid signature");
  46.         return null;
  47.     }
  48.     catch (Exception e)
  49.     {
  50.         return null;
  51.     }
  52.     return data;
  53. }
复制代码
来源:https://www.cnblogs.com/snail-wn/archive/2023/02/21/17141894.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具