This is the 11th day of my participation in the More text Challenge. For more details, see more text Challenge

I accidentally dug up code from years ago and I realized I was really young. For Redis cluster access to Spring is really the bulk of the day. At that time, I deliberately solved a bug in a scene. The redis cluster automatically captures the latest cluster status when the redis cluster is down. But now I have not used the cluster. So was the bug not configured properly or did it exist? This still needs the author follow-up to continue to verify!!

The previous article detailed Redis curD operation and cluster setup. Now we start to integrate it into our actual projects. My project is using the standard SSM framework, SSM framework is not mentioned here, directly start integration.

  • First introduce our JAR package in Maven management
<! <dependency> <groupId>org.springframework.data</groupId> < artifactId > spring - data - redis < / artifactId > < version > 1.7.2. RELEASE < / version > < / dependency > <! -- Redis cache Jar --> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version>  </dependency> <! --> < span style = "color: RGB (50, 50, 50);Copy the code
  • We can configure Redis in the Spring configuration file, but in order to separate Redis easily modified I will uninstall it in another XML file, just introduce the Redis configuration file in the Spring configuration file.

  • All records below are operated from the Redis configuration file.

Redis connection pool configuration

  • This will only set some basic properties of the connection pool, such as the maximum number of connections, pre-connection attribute determination, etc
<bean id="redisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
		<property name="maxTotal" value="${redis.maxTotal}" />
		<property name="maxIdle" value="${redis.maxIdle}" />
		<property name="maxWaitMillis" value="${redis.maxWait}" />
		<property name="testOnBorrow" value="${redis.testOnBorrow}" />
	</bean>
Copy the code
  • MaxIdle: controls the maximum number of Idle Jedis instances in a pool.

  • Whether to perform alidate in advance when a Jedis instance is borrowed; If true, the resulting Instances of Jedis are available

  • MaxWaitMillis: Indicates the maximum wait time for a Jedis instance to borrow. If the wait time is longer than this, a JedisConnectionException is raised.

Redis cluster configuration

Here we are bringing the Redis service we started in the last article to the project. ClusterNodes is our Redis service one by one.

<! <bean id="redisClusterConfig" > class="org.springframework.data.redis.connection.RedisClusterConfiguration"> <property name="maxRedirects" value="3"></property> <property name="clusterNodes"> <set> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" Value ="127.0.0.1"></constructor-arg> <constructor-arg name="port" value="7000"></constructor-arg> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" Value ="127.0.0.1"></constructor-arg> <constructor-arg name="port" value="7004"></constructor-arg> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" Value ="127.0.0.1"></constructor-arg> <constructor-arg name="port" value="7005"></constructor-arg> </bean> </set> </property> </bean>Copy the code

Redis connection factory

We introduced the above Redis service node and connection pool into the factory and have a project to produce a usable Jedis to provide us with cached CURD operations!!

<! - ReDis connection factory - > < bean id = "redis4CacheConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <constructor-arg name="clusterConfig" ref="redisClusterConfig" /> <property name="timeout" value="${redis.timeout}" /> <property name="poolConfig" ref="redisPoolConfig" /> </bean>Copy the code

Redis template

Provide jedis to operate we will put the path template inside for us to call! .

<! - store serialized - > < bean name = "stringRedisSerializer" class = "org. Springframework. Data. Redis. Serializer. StringRedisSerializer" / > <! Cluster Resis - use the template - > < bean id = "clusterRedisTemplate" class = "org. Springframework. Data. Redis. Core. RedisTemplate" > < property name="connectionFactory" ref="redis4CacheConnectionFactory" /> <property name="keySerializer" ref="stringRedisSerializer" /> <property name="hashKeySerializer" ref="stringRedisSerializer" /> <property name="valueSerializer" ref="stringRedisSerializer" /> <property name="hashValueSerializer" ref="stringRedisSerializer" /> </bean>Copy the code

Project called

Jedis is already configured in the configuration file, we only need to use this template to CURD Redis. Here’s a simple example

clusterRedisTemplate.execute(new RedisCallback<Long>() { public Long doInRedis(RedisConnection connection) throws DataAccessException { byte[] keyb = key.getBytes(); byte[] valueb = toByteArray(value); If (connection.exists(keyb)) {// Delete the original data connection.del(keyb); } connection.set(keyb, valueb); return 1L; }});Copy the code

Source probe

RedisClusterConfiguration class we passed in the Redis service node, we set the property and then began to do the following code in the class

And then we pass in those nodes in the factory,

The factory provides me with an AfterProperties method, which means a method that is executed after these parameters are set.

Here we see the creatPool method, which creates a connection in the connection pool

Bug to solve

The deployment will be a problem, it is in the project, each initialization heavy in the pool when they choose a Redis service connections are available, and when the Redis service outage our project will continue to connect the Redis service, we have to start new projects, projects will anew from the connection pool to choose new Redis service.

  • I refactor the connection pool every time I operate Redis. This ensures that I’m always looking for a valid Redis service in the connection pool.
  • The solution is to inject the RedisNode into the project and execute the creatPool method we saw last time each time
Redis template into * * * / / @ Resource private RedisClusterConfiguration redisClusterConfig; private JedisConnectionFactory redis4CacheConnectionFactory; @Resource private RedisTemplate<String, Object> clusterRedisTemplate; / / refactoring connection pool private void init () {redis4CacheConnectionFactory = new JedisConnectionFactory (redisClusterConfig); redis4CacheConnectionFactory.afterPropertiesSet(); clusterRedisTemplate.setConnectionFactory(redis4CacheConnectionFactory); }Copy the code

The connection pool is initialized each time, which costs a lot of performance on the connection pool. There is no solution for the moment, but I initially want to detect the Redis service in the Redis cluster through Redis Sentinel. When Redis is down, sentinel will inform the project to rebuild the connection pool and reconnect to the new Redis service through the API provided by Sentinel