👉Docker builds Redis Cluster

I think it is useless to look at every knowledge point without doing it. You have to use it more or less a few times on your hand to make an impression on it.

The Redis Cluster environment was built yesterday, so let’s play the Redis publish/subscribe mode today

Like a sentence: “eight hours for life, eight hours for development”.

‘😁.

SpringBoot implements publish/subscribe with Redis cluster configuration

One, foreword

In fact, from the code level, there is no change, the main change is about Redis configuration needs to be changed to the cluster configuration, before contact with Redis, then just need to look at the Redis cluster configuration file.

If you are interested in the Redis publish/subscribe implementation, you can read on.

Publish/subscribe mode: The so-called publish/subscribe mode, in fact, is the same meaning as you follow the wechat public number.

For example, if you subscribe to two wechat public accounts (one is called Youth Hunan and the other is called CCTV News), if I subscribe to Youth Hunan, one day CCTV releases a new news, you can receive it, but I do not follow it, I cannot receive it. But a week to see young university learning release Wang Bingbing called you to study, you and I have subscribed, can receive.

Two, preliminary preparation

Both profiles are available.

Standalone is also possible, want to build a Cluster to play together can 👉Docker build Redis Cluster environment.

2.1 Project Structure

2.2 Dependent JAR packages

I’m here because it’s customary to create maven projects and then pull out the SpringBoot version for easy version control.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.52.</version> <relativePath/> <! -- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId>  <artifactId>commons-pool2</artifactId> <version>2.43.</version>
    </dependency>
     <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.272.</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.1820.</version>
    </dependency>
</dependencies>
Copy the code

2.3. Yml Configuration file

Standalone configuration file

spring:
  redis:
    database: 0
    port: 6379
    host: localhost
    password:
    lettuce:
      pool:
        # maximum number of connections in the pool (use negative values to indicate no limit)
        max-active: 1024
        Maximum connection pool blocking wait time (negative value indicates no limit)
        max-wait: 10000
        The maximum number of free connections in the connection pool
        max-idle: 200
        Minimum free connection in connection pool
        min-idle: 0
    Connection timeout (ms)
    timeout: 10000
Copy the code

Redis cluster configuration file

server:
  port: 8089
spring:
  application:
    name: springboot-redis
  redis:
    password: 1234
    cluster:
      nodes:
        - IP address: 6379
        - IP address: 6380
        - IP address: 6381
        - IP address: 6382
        - IP address: 6383
        - IP address: 6384
      max-redirects: 3  Get the maximum number of failed redirects
    lettuce:
      pool:
        max-active: 1000  # maximum number of connections in the pool (use negative values to indicate no limit)
        max-idle: 10 The maximum number of free connections in the connection pool
        min-idle: 5 Minimum free connection in connection pool

# = = = = = = = = = = = jedis configuration way = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# jedis:
# pool:
# maximum number of connections in the pool (use negative values to indicate that there is no limit)
# max-wait: -1ms
# max-idle: 10 # Maximum number of idle connections in the connection pool
# min-idle: 5 # Minimum idle connection in connection pool
#
Copy the code

Three, coding

3.1, the config layer

Redis configuration class

import com.crush.ps.subscribe.AConsumerRedisListener;
import com.crush.ps.subscribe.BConsumerRedisListener;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/** * RedisTemplate serialization/reserialization * 2. Listen for messages@author cuberxp
 * @since 1.0.0
 * Create time 2020/1/23 0:06
 */
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig {

    @Autowired
    AConsumerRedisListener aConsumerRedisListener;

    @Autowired
    BConsumerRedisListener bConsumerRedisListener;

    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory redisConnectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        // Add a message listener to the (possibly running) container. If the container is running, the listener starts receiving (matching) messages as soon as possible.
        // A subscribed topica and Topicb channels
        container.addMessageListener(aConsumerRedisListener, new PatternTopic("topica"));
        container.addMessageListener(aConsumerRedisListener, new PatternTopic("topicb"));

        // B only subscribes to topicb channel
        container.addMessageListener(bConsumerRedisListener, new PatternTopic("topicb"));
        return container;
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // Set the serialization of value hashValue values
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<Object>(
                Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(om);
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashValueSerializer(serializer);
        //key hasKey serialization
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.afterPropertiesSet();
        returnredisTemplate; }}Copy the code

3.2 Subscribers

I’ve put two subscribers here just to show you the example.

A consumer

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

/ * * *@authorCrush * MessageListener: Listener for messages published in Redis. * /
@Component
public class AConsumerRedisListener implements MessageListener {

    @Autowired
    private  RedisTemplate<String, Object> redisTemplate;

     / * * *@paramMessage Indicates the data to be sent@paramChannel pattern * /
    @Override
    public void onMessage(Message message, byte[] pattern) {
        doBusiness(message);
    }

    /** * Deserialize Deserialize an object from a given binary. *@param message
     */
    public void doBusiness(Message message) {
        Object value = redisTemplate.getValueSerializer().deserialize(message.getBody());
        System.out.println("A==>consumer message: "+ value.toString()); }}Copy the code

B Consumer:

package com.crush.ps.subscribe;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

/ * * *@author crush
 */
@Component
public class BConsumerRedisListener implements MessageListener {

    @Autowired
    private  RedisTemplate<String, Object> redisTemplate;

    / * * *@paramMessage Indicates the data to be sent@paramChannel pattern * /
    @Override
    public void onMessage(Message message, byte[] pattern) {
        doBusiness(message);
    }

    /** * Deserialize Deserialize an object from a given binary. *@param message
     */
    public void doBusiness(Message message) {
        Object value = redisTemplate.getValueSerializer().deserialize(message.getBody());
        System.out.println("B==>consumer message: "+ value.toString()); }}Copy the code

The AnnouncementMessage entity class

AnnouncementMessage is a self-written entity class that delivers messages

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;

/ * * *@author crush
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AnnouncementMessage implements Serializable {

    private static final long serialVersionUID = 8632296967087444509L;

    /** * Bulletin id */
    private String id;

    /**
     * 公告内容
     */
    private String content;
}
Copy the code

Four, test,

@SpringBootTest
public class SubscribeTest {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Test
    public void testSubscribe(a) {
        String achannel = "topica";
        String bchannel = "topicb";
        
        redisTemplate.convertAndSend(achannel, "hello world");
        
        redisTemplate.convertAndSend(bchannel, new AnnouncementMessage("1"."Mock notification")); }}Copy the code

Results:

A==> Consumer message: Hello world A==> Consumer message: AnnouncementMessage(id=1, content= simulated announcement) B==> Consumer Message: AnnouncementMessage(id=1, content= simulated announcement)Copy the code

Because consumer A subscribes to two channels and consumer B subscribes to only one channel, consumer A will have one more channel.

Note: The test needs to start the main startup class to facilitate the view of the output. (The main launcher is written by itself, no other notes, just plain old)

Five, talk to yourself

I don’t know what it is like for everyone to learn, but the feeling of the blogger is that what he has learned should be sorted out by himself or put into practice. I think this way will be more profound for understanding and memory.

If there is any deficiency, please do not add!! 😁

Have doubt place, also can leave a message or private letter, will reply for the first time. 👩 💻

That’s all for this article. See you in the next one. 👉 an article implementing message queues with Redis (still being written)