Dubbox 基本特性之结果缓存

3.3 Dubbo结果缓存

 

3.3.1结果缓存

 

  缓存的好处不用多说,在传统的业务开发中,引入缓存可以帮助减轻数据库的压力,在分布式的系统中,引入缓存有两种方式,第一种是在调用者,也就是消费者端引入缓存,如果能够命中缓存,则默认读取缓存中的内容,不需要再进行远程调用,这样就减少了一次IO 请求,也能减少服务提供者的压力,第二种就是在服务提供者提供缓存,同样的请求,把对请求的结果缓存在某个地方,比如Redis,或者java内存中,亦或者第三方的内存容器里,当数据库有更新的时候,同步更新内存,当新的请求在缓存中没有命中的时候,就会击穿缓存落到数据库实例上。

  以上就是缓存设计的基本也是最简单的实现方式,不过如何提高缓存的命中率,有很多的算法,有Least Frequently Used(LFU),LeastRecently User(LRU),First in First out(FIFO)等等的算法。

这里不是我们讨论的重点,详细可以参考http://blog.jobbole.com/30940/

  Dubbo也支持缓存,并且是在服务消费者实现了缓存,因为Dubbo是一个纯粹的服务调用框架,所以它并没有实现高性能高命中的缓存策略,其实也没有办法实现,因为没有具体的业务场景,如何提高缓存命中率,跟业务是息息相关的,哪些是热点数据,在具体业务中才会知道,所以Dubbo只提供了三种缓存方案

本小节,只对LRU的实现给出基本Demo,其他的算法实现将在后面的章节再一起分析

 

 

3.3.2 LRU缓存Demo的基本实现

 

  因为刚才已经说了,Dubbo的缓存是在服务消费者调用端进行配置的,所以服务提供者端,不需要做任何特殊的处理,我们按照惯例,先定义一个接口(服务消费者和服务提供者端同路径下都要有):

package org.bazinga.service;

public interface CacheService {
	
	public String getResultByName(String name);

}

服务提供者给出具体的实现CacheServiceImpl.java:

package org.bazinga.service.impl;

import java.util.concurrent.atomic.AtomicInteger;

import org.bazinga.service.CacheService;

public class CacheServiceImpl implements CacheService {
	
	private AtomicInteger index = new AtomicInteger();

	public String getResultByName(String name) {
		
		Integer callCount = index.getAndIncrement();
		
		System.out.println("paramter is "+ name +" call time is "+ callCount);
		
		if(name == null){
			return "hello hero";
		}else if(name.equals("Lyn")){
			return "hello Lyn";
		}else{
			return "hello War3";
		}
	}

}
服务提供者端的配置文件也不要做什么大改变,与普通的dubbo提供者配置文件是一样的spring-dubbo-provider-cache.xml



       
    
    
     
    
    
    
           
    
    
    
测试类DubboxProviderCacheService.java:

package org.bazinga.service.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DubboxProviderCacheService {

	public static void main(String[] args) throws InterruptedException {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
				"spring-dubbo-provider-cache.xml");
		context.start();
		Thread.sleep(2000000l);
	}

}

服务提供者的配置与普通的dubbo配置是一致的,接下来就是服务消费者Demo的编写,其实与上面的验证或者异步调用一样,都很简单,甚至更加简单,只要在配置文件中加入一个简单的配置就可以轻松地完成缓存的配置,我们在服务消费者端同package下引入的CacheService.java,然后就是配置文件了spring-dubbo-consumer-cache.xml,其实比普通的配置文件就多了一个标签”cache=lru”:



       
    
    
     
    
     
    

就是这么简单的配置就可以完成这样缓存的功能了,编写测试类:

package org.bazinga.service.test;

import org.bazinga.service.CacheService;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DubboConsumerCacheService {

	public static void main(String[] args) throws InterruptedException {
		
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
				"spring-dubbo-consumer-cache.xml");
		context.start();
		
		CacheService cacheService = (CacheService)context.getBean("cacheService");
		
		for(int i = 0;i <100;i++){
			System.out.println(cacheService.getResultByName("Lyn"));
		}
		
	}

}

好了,到此为止,所有的配置文件就已经完成了,我们进入测试环节,我们在CacheServiceImpl.java记录了被调用的次数,服务消费者循环调用了100次,如果正常情况下,服务提供者的控制台应该打印被调用了100次,引入缓存之后,服务消费者缓存了结果,所以调用的次数被大大减小

,我们先启动DubboxProviderCacheService.java的main函数,然后再启动DubboConsumerCacheService.java的main函数:

服务消费者的控制台打印结果:

Dubbox 基本特性之结果缓存_第1张图片

“Hello Lyn”这样的字段重复了100遍,我们再看看关键的服务提供端的控制台打印消息:

可以看到服务提供者只被消费了一次,这样就说明缓存生效了,虽然服务调用方调用了100次,但是真正请求发送到服务提供者的只有一次,LRU缓存算法就是如此,把最近最少使用的缓存对象给踢走,实现的策略就是把新的请求和对应的请求结果放在缓存的顶部,当缓存达到容量极限的时候,把底部对象剔除,所以经常被读取的缓存对象就会一直呆在缓存池中。有两种方法可以实现我,Array 或者是linked list

 

 

3.3.3 本章小结

 

  本章只是简单的介绍了一下Dubbo对缓存的支持,简单的写了一个基于LRU的Demo,帮助大家入门对本模块的理解,更加详细的缓存,在下面的章节会再具体介绍。




你可能感兴趣的:(dubbox,Dubbox实战)