pox file:
<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> </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>
Application:
import java.util.HashSet; import java.util.Set; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.tomcat.jdbc.pool.DataSource; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.embedded.ServletListenerRegistrationBean; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; org.springframework.context.annotation.ComponentScan Import; Import org.springframework.core.io.support.PathMatchingResourcePatternResolver; Import org.springframework.jdbc.datasource.DataSourceTransactionManager; Import the org.springframework.transaction.PlatformTransactionManager; Import com.roncoo.eshop .inventory.listener.InitListener; Import redis.clients.jedis.HostAndPort; Import redis.clients.jedis.JedisCluster; @EnableAutoConfiguration // Bean automatically loads all necessary application class @SpringBootApplication // start @ComponentScan // scan packages @MapperScan ( "com.roncoo.eshop.inventory.mapper") // start entry function public class the Application { // build the data source @Bean @ConfigurationProperties (prefix =" spring.datasource ") public the dataSource the dataSource () { return new DataSource(); } //构建MyBatis的入口类:SqlSessionFactory @Bean public SqlSessionFactory sqlSessionFactoryBean1() 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()); } @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; } //注册监听器 线程池+内存队列初始化 @SuppressWarnings({ "rawtypes", "unchecked" }) @Bean public ServletListenerRegistrationBean servletListenerRegistrationBean(){ ServletListenerRegistrationBean servletListenerRegistrationBean= new ServletListenerRegistrationBean(); //添加listener servletListenerRegistrationBean.setListener(new InitListener()); return servletListenerRegistrationBean; } //SpringBoot 启动入口的方法 public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
When updating data, based on the unique identification data, the route after the operation, sent to the internal queue of a jvm
When reading data, if the data is not found in the cache, then read the data again to update the cache + operation, after the unique identification in accordance with the route, also sends the same internal queue jvm
A queue corresponds to a worker thread
Each worker thread to get the corresponding serial operation, and then performing a one
In this case, a change of operating data, execute, delete the cache, and then go to update the database, but is not yet complete update
At this time, if a read request over an empty cache read, then the first cache may transmit the request to update the queue, then the backlog in the queue will be, and then waits for the synchronization cache update complete
There is an optimization point, a queue, in fact, more than one update cache request strung together does not make sense, so you can do the filtering, if the queue has been found to have a request to update the cache,
Then you do not update the requested operation came alive again go directly in front of the waiting for the update to complete the requested operation
After that queue corresponding work to be done to modify the database thread on one operation at will to perform an action, that is, the cache update operation, then reads the latest values from the database, and then write cache
If the request waiting time range, to continue the polling can take values found, then return directly; if the waiting time exceeds a certain length of time request, then this time the old value of the current read directly from the database
Specific implementation steps:
1, the thread pool + memory queue initialization
ServletContextListener which do, listener, will start along with the entire web application, initialize, initialize the thread pool to build similar
spring boot application, Application, engage a listener registration