(1)监听多个kafka topic,每个kafka topic对应一个服务(简化一下,监听一个kafka topic)(2)如果一个服务发生了数据变更,那么就发送一个消息到kafka topic中(3)缓存数据生产服务监听到了消息以后,就发送请求到对应的服务中调用接口以及拉取数据,此时是从mysql中查询的(4)缓存数据生产服务拉取到了数据之后,会将数据在本地缓存中写入一份,就是ehcache中(5)同时会将数据在redis中写入一份
2、spring boot+mybatis+redis框架整合搭建
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.5.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.1.43</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestone</id> <url>https://repo.spring.io/libs-release</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-milestone</id> <url>https://repo.spring.io/libs-release</url> </pluginRepository> </pluginRepositories>
@EnableAutoConfiguration @SpringBootApplication @ComponentScan @MapperScan("com.roncoo.eshop.inventory.mapper") public class Application { @Bean @ConfigurationProperties(prefix="spring.datasource") public DataSource dataSource() { return new org.apache.tomcat.jdbc.pool.DataSource(); } @Bean public SqlSessionFactory sqlSessionFactoryBean() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource()); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mybatis/*.xml")); return sqlSessionFactoryBean.getObject(); } @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public JedisCluster JedisClusterFactory() { Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>(); jedisClusterNodes.add(new HostAndPort("192.168.31.19", 7003)); jedisClusterNodes.add(new HostAndPort("192.168.31.19", 7004)); jedisClusterNodes.add(new HostAndPort("192.168.31.227", 7006)); JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes); return jedisCluster; } }
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver
3.缓存:本地缓存+redis分布式缓存+nginx缓存
3.1 ehcache缓存
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.8.3</version> </dependency>
@Configuration @EnableCaching public class CacheConfiguration { @Bean public EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){ EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean(); cacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml")); cacheManagerFactoryBean.setShared(true); return cacheManagerFactoryBean; } @Bean public EhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean bean){ return new EhCacheCacheManager(bean.getObject()); } }
ehcache.xml <?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false"> <diskStore path="java.io.tmpdir/Tmp_EhCache" /> <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0" timeToLiveSeconds="0" memoryStoreEvictionPolicy="LRU" /> <cache name="local" eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0" timeToLiveSeconds="0" memoryStoreEvictionPolicy="LRU" /> </ehcache>
@Service("cacheService") public class CacheServiceImpl implements CacheService { public static final String CACHE_NAME = "local"; @Cacheable(value = CACHE_NAME, key = "'key_'+#id") public UserInfo getById(Long id){ return null; } @CachePut(value = CACHE_NAME, key = "'key_'+#userInfo.getId()") public UserInfo saveUserInfo(UserInfo userInfo) { return UserInfo; } }
@Controller public class CacheTestController { @Resource private CacheService cacheService; @RequestMapping("/testPutCache") @ResponseBody public void testPutCache(UserInfo userInfo) { System.out.println(userInfo.getId() + ":" + userInfo.getName()); cacheService.saveProductInfo(userInfo); } @RequestMapping("/testGetCache") @ResponseBody public ProductInfo testGetCache(Long id) { UserInfo userInfo = cacheService.findById(id); System.out.println(userInfo.getId() + ":" + userInfo.getName()); return productInfo; } }
3.2缓存注解说明:
@CachePut
应用到写数据的方法上,如新增/修改方法,调用方法时会自动把相应的数据放入缓存。
public @interface CachePut { String[] value(); //缓存的名字,可以把数据写到多个缓存 String key() default ""; //缓存key,如果不指定将使用默认的KeyGenerator生成,后边介绍 String condition() default ""; //满足缓存条件的数据才会放入缓存,condition在调用方法之前和之后都会判断 String unless() default ""; //用于否决缓存更新的,不像condition,该表达只在方法执行之后判断,此时可以拿到返回值result进行判断了 }
②@CacheEvict
即应用到移除数据的方法上,如删除方法,调用方法时会从缓存中移除相应的数据。
public @interface CacheEvict { String[] value(); //请参考@CachePut String key() default ""; //请参考@CachePut String condition() default ""; //请参考@CachePut boolean allEntries() default false; //是否移除所有数据 boolean beforeInvocation() default false;//是调用方法之前移除/还是调用之后移除 }
③Cacheable
应用到读取数据的方法上,即可缓存的方法,如查找方法:先从缓存中读取,如果没有再调用方法获取数据,然后把数据添加到缓存中。
public @interface Cacheable { String[] value(); //请参考@CachePut String key() default ""; //请参考@CachePut String condition() default "";//请参考@CachePut String unless() default ""; //请参考@CachePut }