• 【开发篇】十一、SpringBoot缓存底层实现技术的切换为Ehcache、Redis、Memcached



    SpringBoot提供了缓存的统一整合接口,方便缓存技术的开发与管理:

    • Generic
    • JCache
    • Ehcache
    • Hazelcast
    • Infinispan
    • Couchbase
    • Redis
    • Caffeine
    • Simple(默认)
    • memcached

    0、补充:数据淘汰策略

    当遇到某些场景,如到达缓存最大内存时还有数据往进来写,此时就会按照配置的数据淘汰策略删数据,常用的淘汰策略有:

    • volatile-lru:挑选最近最少使用的数据淘汰
    • volatile-lfu:挑选最近使用次数最少的数据淘汰
    • volatile-ttl:挑选将要过期的数据淘汰
    • volatile-random:任意选择数据淘汰

    简单说,LRU就是最近没怎么用到的数据,LFU就是使用最少的数据:

    在这里插入图片描述
    如上图,9s内,age这个key的数据最近一次使用是第5s的时候,其他数据则在第7、8、9秒时访问过,按LRU就淘汰它。但按LFU,最少使用的是gender这个key的数据,只用1次,LFU下淘汰它。

    1、切换为Ehcache

    首先引入Ehcache依赖:

    <dependency>   
    	<groupId>net.sf.ehcachegroupId>    
    	<artifactId>ehcacheartifactId>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    版本不用管,spring-boot-parent中依赖管理有这个依赖,用boot调好的版本就好:

    在这里插入图片描述
    再将缓存类型设置为ehcache:

    spring:  
      cache:    
        type: ehcache    
        ehcache:      
          config: classpath:ehcache.xml
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    类路径resources下提供ehcache配置文件ehcache.xml:

    
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
             updateCheck="false">
                 
            
        
           
            
            
            
            
            
        <defaultCache           
        	eternal="false"            
        	diskPersistent="false"            
        	maxElementsInMemory="1000"           
        	overflowToDisk="false"           
        	timeToIdleSeconds="60"           
        	timeToLiveSeconds="60"           
        	memoryStoreEvictionPolicy="LRU" />
    ehcache>
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    为了适配之前代码里@Cacheable的value属性:

    //不写value那就是defaultCache
    @CachePut(value = "telCode",key = "#tel")
    ...
    
    • 1
    • 2
    • 3

    可在默认存储区外再加一块区域的定义:

    在这里插入图片描述

    重启服务,测试下上篇的验证码的生成与校验接口都正常,这就完成了底层缓存技术的切换,从默认的Simple切换为Ehcache。SpringBoot提供了一套标准的Cache解决方案接口,换底层的技术实现并不用去改动原先的代码实现,这就是设计优雅的地方!

    2、切换为Redis

    加入Redis坐标(缓存供应商实现):

    <dependency>   
    	<groupId>org.springframework.bootgroupId>    
    	<artifactId>spring-boot-starter-data-redisartifactId>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    修改配置,这里除了redis.host,过期时间等配置也写在了配置文件里,其实应该用配置类,不同的key设置不同的过期时间:

    spring:  
      redis:    
        host: localhost    
        port: 6379  
      cache:    
        type: redis    
        redis:
          use-key-prefix: true      # 是否使用前缀名(肯定要用,不用前缀,很容易重复,导致bug)
          key-prefix: sms_          # 追加自定义前缀名,除了代码里的前缀key,再统一加一个      
          time-to-live: 10s         # 有效时长     
          cache-null-values: false  # 是否允许存储空值
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    到此,切换完成,调用下之前生成验证码的接口:

    在这里插入图片描述

    3、切换为memcached–安装与启停

    memcached的安装:https://www.runoob.com/memcached/window-install-memcached.html ,解压后进入memcached目录:

    在这里插入图片描述

    打开cmd窗口执行以下指令:

    # 安装
    memcached.exe -d install
    
    • 1
    • 2

    可能报错安装失败:

    在这里插入图片描述
    搜索cmd,右键以管理员身份运行,重新打开cmd执行以上安装指令即可。

    在这里插入图片描述
    启动:

    memcached.exe -d start
    
    • 1

    停止:

    memcached.exe -d stop
    
    • 1

    4、切换为memcached–整合

    关于memcached客户端选择:

    • Memcached Client for Java:最早期客户端,稳定可靠,用户群广
    • SpyMemcached:效率更高
    • Xmemcached:并发处理更好

    这里选择Xmemcached,SpringBoot未提供对memcached的整合,需要使用硬编码方式实现客户端初始化管理。首先导入Xmemcache坐标(缓存供应商实现):

    
    <dependency>    
    	<groupId>com.googlecode.xmemcachedgroupId>
    	<artifactId>xmemcachedartifactId>    
    	<version>2.4.7version>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    既然不受Spring管控,那在配置类中自己@Bean来创建一个客户端操作对象:

    @Configuration
    public class XMemcachedConfig {      
    	@Bean    
    	public MemcachedClient getMemcachedClinet() throws IOException {        
    		MemcachedClientBuilder builder = new XMemcachedClientBuilder("localhost:11211");        
    		MemcachedClient memcachedClient = builder.build();        
    		return memcachedClient;   
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    改造验证码的获取与校验方法:set存get取

    @Service
    public class SMSCodeServiceMemcacheImpl implements SMSCodeService {    
    
    	@Autowired   
    	private MemcachedClient memcachedClient;
    	    
    	@Override    
    	public String sendCodeToSMS(String tele) {        
    		String code = CodeUtils.generator(tele);       //将数据加入memcache        
    		try {            
    			memcachedClient.set(tele,0,code);		// key,timeout,value        
    		} catch (Exception e) {            
    			e.printStackTrace();        
    		}       
    		return code;    
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    @Override    
    public boolean checkCode(String tel,String code) {        
    	String value = null;        
    	try {           
    		value = memcachedClient.get(tel) + "";      //Object转String,别toString,会空指针
    	} catch (Exception e) {            
    		e.printStackTrace();       
    	}         
    	return code.equals(value);    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    有点low,虽然Spring容器不管控我,自然也不会读我写application.yaml中的配置,但我可以自己写,然后自己读取yaml,然后给代码中用,这样配置统一管理,优雅且合理(当然你也可以定义个变量,然后@Value从yaml中取,看配置的数量多不多吧)。首先在yaml中写配置文件:

    memcached:    
      # memcached服务器地址    
      servers: localhost:11211    
      # 连接池的数量    
      poolSize: 10    
      # 设置默认操作超时    
      opTimeout: 3000
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    定义对应的接参实体类,加载yaml配置:

    @Component
    @ConfigurationProperties(prefix = "memcached")
    @Data
    public class XMemcachedProperties {    
    
    	private String servers;    
    	
    	private Integer poolSize;    
    	
    	private Long opTimeout;
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    此时,上面创建客户端操作Bean的代码可以优化为:

    @Configuration
    public class XMemcachedConfig {      
    
    	@Resource
    	private XMemcachedProperties xMemcachedProperties;
    	
    	@Bean    
    	public MemcachedClient getMemcachedClinet() throws IOException {   
    	     
    		MemcachedClientBuilder builder = new XMemcachedClientBuilder(xMemcachedProperties.getServers());  
    
      		builder.setConnectionPoolSize(xMemcachedProperties.getPoolSize());
    		     
    		MemcachedClient memcachedClient = builder.build();        
    		
    		return memcachedClient;  
    		 
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    切换完成,调用下之前的接口,验证码缓存的读写都正常。总结就是:

    • 客户端操作Bean的初始化
    • get、set读写

    这地方要关注的重点是自己操作客户端对象,干Spring没干的事,以及yaml配置自己管理自己读取。

  • 相关阅读:
    【C++】内联函数&auto&范围for循环&nullptr
    微信小程序开发---自定义底部tabBar
    kong安装与配置
    紫光同创FPGA图像视频采集系统,提供2套PDS工程源码和技术支持
    iNFTnews|FTX一夜崩塌,但Web3仍前途光明
    HTML期末作业 蛋糕bootstrap响应式网站html+css+javascript+jquery+bootstarp
    【CesiumJS入门】(12)Vite+Vue3+Cesium 简易安装与配置
    Web3与Web3.0: Web3指的是去中心化和基于区块链的网络,Web3.0指的是链接或语义网络。
    node.js的路径、fs模块
    LeetCode437:路径总和III
  • 原文地址:https://blog.csdn.net/llg___/article/details/133361659