首页 > 其他分享 >关于缓存系统的mutex模式实现

关于缓存系统的mutex模式实现

时间:2023-09-14 14:07:59浏览次数:36  
标签:缓存 categoryListStr 模式 重试 mutex key categoryListMemcachedKey memcached


这篇blog是在上一家互联网公司某产品开发过程中的一些经验总结,整理一下分享上来。

 

关于mutex模式:

对于高并发大访问量的应用,一般都会在数据库访问前加一层缓存系统。

但是如果某一时刻某个缓存的key失效,而reload该key缓存的时间又比较长,导致大量的请求直接访问数据库,则会直接将数据库击垮。

 

解决方案:

当在缓存中获取某个key为null时,add一个mutex key,并进行数据的reload工作,数据reload后删除该mutex key。

如果另外一个线程访问该key也为null,则也会add一个mutex key,但发现add不进去(已经包含了该mutex key)。这时设置这个线程sleep一段时间后,再重试(可以设置重试次数)。如果全部重试完还是没有reload完数据则响应一个异常状态或响应304给终端。

 

程序部分伪码实现(缓存系统用的是Memcached):

//根据业务生成一个Cache Key.
		String categoryListMemcachedKey = genCategoryListCacheKey(parentId);
		MemCache memcached=MemCache.getInstance();
		//该业务Key不存在或失效
		if(memcached.get(categoryListMemcachedKey)==null){
			//设置该业务键的mutex key.
			String mutexKey=categoryListMemcachedKey+"|mutex";
			if(memcached.add(mutexKey,1*60*1000)==true){//reload in 1min
				//categoryListStr代表数据库查询后构建的结果
				categoryListStr=dbResult;
				if("".equals(categoryListStr)){//set ""相当于没set,高并发请求仍旧会击跨数据库.
					memcached.set(categoryListMemcachedKey,"nodata",new Date(1000*60*1));//防止假数据一直存在缓存中,设置过期时间1min.
				}else{
					memcached.set(categoryListMemcachedKey,categoryListStr);
				}
				//删除mutex key
				memcached.delete(mutexKey);
			}else{//某线程正在load数据
				try {
					Thread.sleep(50);//当前线程睡眠50ms
					categoryListStr=(String)retry(memcached,categoryListMemcachedKey,3);//重试3次
					if(categoryListStr==null){categoryListStr = "nodata";}
				} catch (Throwable e) {
					LogFactory.getLog(MemcachedCacheManager.class).error("Thread sleep error:",e);
				}
			}
		}else{//缓存中已存在该业务key
			System.out.println("There has "+categoryListMemcachedKey+" in memcached!");
			categoryListStr=(String)memcached.get(categoryListMemcachedKey);
		}

上面代码中的重试方法(递归实现):

/** 重试  */
	public static Object retry(MemCache memcached,String key,int tryNum){
		System.out.println("In retry:"+key+" tryNum:"+tryNum+"!");
		if(memcached.get(key)==null){//重试还是取不到数据
			System.out.println("Retry no data!");
			if(tryNum==0){//已达到重试上限
				System.out.println("There is no tryNum "+key+"!");
				return null;//返回null
			}else{
				try {
					Thread.sleep(50);//睡眠50ms
				} catch (Throwable e) {
					e.printStackTrace();
				}
				return retry(memcached,key,--tryNum);//递归重试
			}
		}else{
			System.out.println("Retry have data!");
			return memcached.get(key);
		}
	}

 

参考资料:

关于mutex设计模式:http://timyang.net/programming/memcache-mutex/

 这是新浪某大牛的blog,也是最初看到探讨mutex模式的文章。

 

标签:缓存,categoryListStr,模式,重试,mutex,key,categoryListMemcachedKey,memcached
From: https://blog.51cto.com/u_6978506/7469658

相关文章

  • 设计模式回顾之十二:迭代器模式(Iterator)
    设计模式回顾系列文章:主要针对工作中常用常见的设计模式进行整理、总结,同时分享以供大家拍砖。------------------------------------------------迭代器模式(Iterator)提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。适用于:访问一个聚合对象的内容而......
  • 设计模式回顾之十:工厂方法模式(FactoryMethod)
    设计模式回顾系列文章:主要针对工作中常用常见的设计模式进行整理、总结,同时分享以供大家拍砖。------------------------------------------------工厂方法模式(FactoryMethod)定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。......
  • 设计模式回顾之九:建造者模式(Builder)
    设计模式回顾系列文章:主要针对工作中常用常见的设计模式进行整理、总结,同时分享以供大家拍砖。------------------------------------------------建造者模式(Builder)将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 适用于:当创建复杂对象的算法应该......
  • java/jsp清除jsp缓存
    InJava:HttpServletResponseresponse=(HttpServletResponse)rep;response.setDateHeader("Expires",-1);response.setHeader("Cache_Control","no-cache");response.setHeader("Pragma","no-ca......
  • 抽象工厂模式:创建对象的工厂中的工厂
    在软件开发中,对象的创建是一个常见而重要的任务。不同的对象需要不同的创建方式,而且这些对象可能存在复杂的关联关系。为了解决这些问题,设计模式中有一个特别有用的创建型模式,即抽象工厂模式。本文将介绍抽象工厂模式的概念、使用场景以及示例代码。1.设计模式背景设计模式是......
  • 商品查询业务之解决商品查询的缓存穿透、缓存雪崩、缓存击穿问题(封装工具类)
    商品查询业务之解决商品查询的缓存穿透、缓存雪崩、缓存击穿问题(封装工具类)核心思路如下:在原来的逻辑中,我们如果发现这个数据在mysql中不存在,直接就返回404了,这样是会存在缓存穿透问题的现在的逻辑中:如果这个数据不存在,我们不会返回404,还是会把这个数据写入到Redis中,并且将v......
  • 设计模式之:1单例模式
    1 单例模式1.1     引言单例模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点。1.2     经典模式publicclassSingleton{privatestaticSingletoninstance;private......
  • 【设计模式】状态模式State:通过有限状态机监控功能的 "状态变化"
    (目录)状态模式的应用场景非常广泛,比如:线上购物订单、手机支付、音乐播放器、游戏、工作流引擎等场景。状态模式设计的初衷是应对同一个对象里不同状态变化时的不同行为的变化。模式原理原始定义是:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了自己的......
  • 【设计模式】策略模式Strategy:解决不同活动策略营销推荐场景
    (目录)模板方法模式能帮助我们进行公有方法的抽取,起到快速复用和扩展的作用。另一种快速复用和扩展代码的行为型模式:策略模式。策略模式在实际的开发中很常用,最常见的应用场景是利用它来替换过多的if-else嵌套的逻辑判断。除此之外,还能结合工厂模式给客户端提供非常灵活的使......
  • 三级模式结构
        ......