CJCMS系列---说说项目中的缓存实现(1)

缓存者,临时文件交换区也。主要就是方便查找,提高查找效率(效率在于读内存速度比读硬盘快)。

  

  大多数的项目的缓存都是通过设定过期时间来做的,可是我对于这样的替换策略不以为然,而且会导致混乱。

  有人说:最让人蛋疼的莫过于命名和缓存了。

  那么缓存蛋疼在哪里呢,那就是容易导致脏数据,缓存不应该成为脏数据,而大多数时间脏数据不可避免。

  

  举一个例子:淘宝商城,我店里有一个商品,当时缓存的库存100,但是赶上光棍节大酬宾,各种并发请求,也许你在买的时候缓存里面还有20,但是100个订单已经下过了,但是点击下单的时候蛋疼的事情来了(当然我觉得淘宝没有这样子的问题啦),你居然下单成功了。我操,我作为店主很郁闷啊,我他娘的到哪里多进口20架米格战斗机啊。

  

  上面的例子,你对缓存应该也有了一种深恶痛绝的感受吧。你这时候笑了,笑我写的程序差,笑我淘宝店的代码是垃圾,没错,这样的脏数据是能够避免的,可是有多少程序员能够注意到这一点呢,我觉得很少。

  

  直入主题上代码,这里先上一部分后面慢慢讲深入,慢慢改进,毕竟真的是在边写文章边写例子。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CJCMS.Framework.Cache
{
    public  class CacheTarget
    {
        /// <summary>
        /// 缓存对象
        /// </summary>
        public object Target { get; set; }

        /// <summary>
        /// 缓存对象最后使用时间
        /// </summary>
        public DateTime LastRefresh { get; set; }
    }
}

  

  1 /******************************************************************
  2 * 作者:                    不要理我 CJ
  3 * 邮件:               [email protected](仅仅支持商业合作洽谈)
  4 * 创建时间:                2012-8-14 19:43:41
  5 * 最后修改时间:            2012-8-14 19:43:41
  6 *
  7 * 未经修改的文件版权属于原作者所有,但是你可以阅读,修改,调试。本项目不建议商用,不能确保稳定性。
  8 * 同时由于项目bug引起的一切问题,原作者概不负责。
  9 *
 10 * 本项目所引用的所有类库,仍然遵循其原本的协议,不得侵害其版权。
 11 *
 12 * 您一旦下载就视为您已经阅读此声明。
 13 *
 14 * 您不可以移除项目中的任何声明。
 15 *******************************************************************/
 16
 17 using System;
 18 using System.Collections.Generic;
 19 using System.Linq;
 20 using System.Text;
 21
 22 namespace CJCMS.Framework.Cache
 23 {
 24     public class CacheTargetManger //: ICacheTargetManger
 25     {
 26         private static Dictionary<string, CacheTarget> _entries = new Dictionary<string, CacheTarget>();
 27
 28         /// <summary>
 29         /// 检测是否缓存空间达到极限,需要使用策略替换
 30         /// </summary>
 31         /// <returns></returns>
 32         public static void CheckIsExpired()
 33         {
 34
 35             AppDomain.MonitoringIsEnabled = true;
 36
 37             AppDomain currAppDomain = System.Threading.Thread.GetDomain();
 38             while (true)
 39             {
 40                 GC.Collect();
 41                 if (currAppDomain.MonitoringSurvivedMemorySize > 50 * 1000 * 1000)
 42                 {
 43                     //最近最少使用策略实现
 44                     DoStrategy();
 45                 }
 46                 else
 47                 {
 48                     break;
 49                 }
 50             }
 51         }
 52         /// <summary>
 53         /// 使用了最近最少使用策略
 54         /// </summary>
 55         public static void DoStrategy()
 56         {
 57             try
 58             {
 59                 Remove(_entries.OrderBy(a => a.Value.LastRefresh).First().Key);
 60             }
 61             catch
 62             {
 63
 64             }
 65         }
 66         /// <summary>
 67         /// 添加新的内容
 68         /// </summary>
 69         /// <param name="key"></param>
 70         /// <param name="cache"></param>
 71         public static void Add(string key, object cache)
 72         {
 73             CacheTarget c = new CacheTarget();
 74             c.Target = cache;
 75             c.LastRefresh = DateTime.Now;
 76             CheckIsExpired();
 77             lock (_entries)
 78             {
 79                 _entries.Add(key, c);
 80             }
 81
 82         }
 83
 84         public static void Update(string key, object cache)
 85         {
 86             CacheTarget c = new CacheTarget();
 87             c.Target = cache;
 88             c.LastRefresh = DateTime.Now;
 89
 90             lock (_entries)
 91             {
 92                 _entries.Remove(key);
 93                 _entries.Add(key, c);
 94             }
 95
 96         }
 97
 98         public static void Save(string key, object cache)
 99         {
100             if (_entries.ContainsKey(key))
101             {
102                 Update(key, cache);
103             }
104             else
105             {
106                 Add(key, cache);
107             }
108         }
109
110         public static void Remove(string key)
111         {
112             lock (_entries)
113             {
114                 _entries.Remove(key);
115             }
116         }
117
118         public static void FuzzyRemove(string fuzzykey)
119         {
120             foreach (KeyValuePair<string, CacheTarget> k in _entries.Where(a => a.Key.Contains(fuzzykey)).ToList())
121             {
122                 Remove(k.Key);
123             }
124         }
125
126         public static void Get(string key, out object result)
127         {
128             try
129             {
130                 CacheTarget c = new CacheTarget();
131                 _entries.TryGetValue(key, out c);
132                 result = c.Target;
133                 Update(key, result);
134             }
135             catch
136             {
137                 result = null;
138             }
139         }
140     }
141 }

大家先看起来代码,具体还没有讲完,我后面再讲。

宝宝跨年乐 刷票 qq 869722304

时间: 2024-10-12 18:04:45

CJCMS系列---说说项目中的缓存实现(1)的相关文章

谈谈MVC项目中的缓存功能设计的相关问题

本文收集一些关于项目中为什么需要使用缓存功能,以及怎么使用等,在实际开发中对缓存的设计的考虑 为什么需要讨论缓存呢? 缓存是一个中大型系统所必须考虑的问题.为了避免每次请求都去访问后台的资源(例如数据库),我们一般会考虑将一些更新不是很频繁的,可以重用的数据,通过一定的方式临时地保存起来,后续的请求根据情况可以直接访问这些保存起来的数据.这种机制就是所谓的缓存机制. 根据缓存的位置不同,可以区分为: 1.客户端缓存(缓存在用户的客户端,例如浏览器) 2.服务器断货(缓存在服务器中,可以缓存在内存

关于vagrant环境下项目中图片缓存的问题

之前用的是iis所以可能没有这些问题,后来换了nginx之后发现图片缓存问题很严重,本项目用的是thinkphp5框架:浏览器.runtime.session.cookie.加参数,后台,所有缓存都清理了图片还是有缓存只能改名才会自动更新.后来发现nginx的配置文件里有下边的一些代码 expires 代表的是缓存时间,如果不想缓存就直接加上红框的那一行字就可以了,或是将expires 改为-1或off(还未尝试是否可行),加上add_header Cache-Control no-store;

Django 项目中设置缓存

一.配置文件settings.py中 # 设置django缓存存放位置为redis数据库,并设置一个默认(default)选项,在redis中(配置文件/etc/redis/redis.conf)开启了RDB持久化储存 # pip install django-redis, 然后在视图中可以通过 from django_redis import get_redis_connection 这个方法和redis数据库进行连接 CACHES = { "default": { "BA

项目中使用缓存的目的?(高并发和高性能)

用缓存,主要有两个用途,一个是高性能,一个是高并发. 1)高性能 假设这么个场景,你有个操作,一个请求过来,吭哧吭哧你各种乱七八糟操作mysql,半天查出来一个结果,耗时600ms.但是这个结果可能接下来几个小时都不会变了,或者变了也可以不用立即反馈给用户.那么此时咋办? 缓存啊,折腾600ms查出来的结果,扔缓存里,一个key对应一个value,下次再有人查,别走mysql折腾600ms了.直接从缓存里,通过一个key查出来一个value,2ms搞定.性能提升300倍. 这就是所谓的高性能.

WebApi系列~实际项目中如何使用HttpClient向web api发异步Get和Post请求并且参数于具体实体类型

本讲比较实际,在WEB端有一个Index和Create方法,用来从web api显示实体列表数据和向api插入实体对象,这就是以往的网站,只不过是把数据持久化过程放到了web pai上面,它的优势不用说,就是跨平台,跨语言,这其实是restFul的功功,一切通讯都变得那个简易,清晰!你再也不用引用程序集了... 先看一下实体的具体效果 我们看到如图,它们在取数据和插数据的时间,走的都是restful标准,都是通过web api实现的,当然,对于通讯来说,要求你的实体必须是可序列化的,这是正常的,

HashMap与redis在项目中的应用

刚从.net转java三个月,这里记录一下在java项目中使用缓存的学习. 因为项目之前的开发人员离职了,在之前的项目上进行维护,对应从来没有接触过java的小白,只能自己多看多理解多动手了. 这个项目原来是没有用java真正意义上的缓存,而是用的静态的HashMap,但是在性能测试的过程中出现了死锁的过程,因为hashmap是不安全的线程,建议使用ConcurrentHashMap这个和.net的Dictonary很像.因为性能测试不通过,所以后来加了redis,其实java的一级缓存ehca

Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问

本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这部分内容需要以下Jar包支持 mysql-connector:MySQL数据库连接驱动,架起服务端与数据库沟通的桥梁: MyBatis:一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架: log4j:Apache的开源项目,一个功能强大的日志组件,提供方便的日志记录: 修改后的pom.xm

【新手总结】在.Net项目中使用Redis作为缓存服务

最近由于项目需要,在系统缓存服务部分上了redis,终于有机会在实际开发中玩一下,之前都是自己随便看看写写,很零碎也没沉淀下来什么,这次算是一个系统学习和实践过程的总结. 和Redis有关的基础知识 Redis是一个开源的分布式NoSql数据库,可以用来做缓存服务.消息队列.数据存储等等,数据类型之丰富,效率之高,简直逆天!没有了解过的可以移步去问度娘~客户端之丰富,足可见它的社区有多强大: 其中C#的客户端就有这么多: 没错,我们的项目里也选择了最热门的StackExchange.Redis作

WPF Step By Step 系列-Prism框架在项目中使用

WPF Step By Step 系列-Prism框架在项目中使用 回顾 上一篇,我们介绍了关于控件模板的用法,本节我们将继续说明WPF更加实用的内容,在大型的项目中如何使用Prism框架,并给予Prism框架来构建基础的应用框架,并且如何来设计项目的架构和模块,下面我们就来一步步开始吧. 本文大纲 1.Prism框架下载和说明 2.Prism项目预览及简单介绍. 3.Prism框架如何在项目中使用. Prism框架下载和说明 Prism框架是针对WPF和Silverlight的MVVM框架,这