Spring Data Redis 实战

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/neweastsun/article/details/87970540

## Spring Data Redis 实战

redis 介绍

redis是使用ANSI C 编写的NOSQL数据库,并提供领域专用语言DSL。其采用客户端/服务器端模式,监听TCP端口并接收命令。客户端发送命令:

SET foo bar

LPUSH mylist val

命令在一个key上执行原子操作,读写一个或多个key值。没有任何竞争条件发生,不需要任何锁机制。redis所有基于key的操作,值都保存在内存中。

redis应用场景

基于内存数据,提升数据库处理效率,特别是有大量写操作,实时统计分析。
实现与memcached一样的缓存功能,但可以修改缓存数据,而不仅是缓存失效。
实现消息功能,redis list可作为队列,实现发布/订阅消息。
计算单元,在redis实例中实现复杂的计算操作,如实现推荐算法引擎。

Spring Data Redis 及 redis 连接器

Spring Data 集成Jedis、JRedis、srp以及Lettuce连接器。在不同连接器之间仅有一组接口保持行为一致性。RedisConnection 和 RedisConnectionFactory 用于从redis中获取活动连接。同时RedisConnectionFactory也处理和后端redis之间的通讯以及把库异常翻译为Spring一致的Dao异常层级,方便在不同连接器间可以不修改代码进行切换。

依赖

Spring data Redis可以支持不同连接器,但好处是只要你的代码基于Spring data Redis api,则与你是用那个连接器无关。你可以通过依赖自由切换连接器。

示例使用jedis连接器:

plugins {
    id 'org.springframework.boot' version '2.1.2.RELEASE'
    id 'java'
}
apply plugin: 'io.spring.dependency-management'

repositories {
    mavenCentral()
}

dependencies {
    compile 'redis.clients:jedis:2.9.0'
    implementation 'org.springframework.boot:spring-boot-starter-data-redis'

    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.8'
}

其中 jackson-databind 实现对象序列化功能。

jedis 连接器基本配置示例

Spring Boot java 配置:

    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        RedisStandaloneConfiguration redisCfg= new RedisStandaloneConfiguration();
        redisCfg.setHostName("localhost");
        redisCfg.setPort(6379);
        redisCfg.setPassword("8888");

        return new JedisConnectionFactory(redisCfg);
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(jedisConnectionFactory());
        Jackson2JsonRedisSerializer jacksonSerializer = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        // 设置value的序列化规则和 key的序列化规则
        template.setValueSerializer(jacksonSerializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();

        return template;
    }

这里指定jackson的ObjectMapper作为序列化工具,实现对象自动转成json字符串进行传输和存储。

基本类型交互

// ValueOperations, BoundValueOperations
stringRedisTemplate.opsForValue().set(key, value); 
stringRedisTemplate.boundValueOps(key).set(value); 

// HashOperations, BoundHashOperations
stringRedisTemplate.opsForHash().put(key, "hashKey", value); 
stringRedisTemplate.boundHashOps(key).put("hashKey", value); 

// ListOperations, BoundListOperations
stringRedisTemplate.opsForList().leftPush(key, value); 
stringRedisTemplate.opsForList().rightPush(key, value); 
stringRedisTemplate.opsForList().rightPop(key, 1, TimeUnit.SECONDS); 
stringRedisTemplate.opsForList().leftPop(key, 1, TimeUnit.SECONDS); 
stringRedisTemplate.boundListOps(key).leftPush(value); 
stringRedisTemplate.boundListOps(key).rightPush(value); 
stringRedisTemplate.boundListOps(key).rightPop(1, TimeUnit.SECONDS); 
stringRedisTemplate.boundListOps(key).leftPop(1, TimeUnit.SECONDS); 

// ZSetOperations, BoundZSetOperations
stringRedisTemplate.opsForZSet().add(key, "player1", 12.0d); 
stringRedisTemplate.opsForZSet().add(key, "player2", 11.0d); 
stringRedisTemplate.boundZSetOps(key).add("player1", 12.0d); 
stringRedisTemplate.boundZSetOps(key).add("player2", 11.0d);

自定义类型操作

自定义类型Student类:

@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Student implements Serializable {

    public enum Gender {
        /**
         * male
         */
        MALE,
        /**
         * female
         */
        FEMALE
    }

    private String id;
    private String name;
    private Gender gender;
    private int grade;
}

存储获取student对象:

    Student student = new Student("Eng2015002", "John Doe", Student.Gender.MALE, 1);

    redisTemplate.opsForValue().set(student.getId(),student);
    Object stu = redisTemplate.opsForValue().get(student.getId());
    log.info("Eng2015002:{}", stu);

jackson自动进行序列化和反序列化。

内置类

Spring Data Redis 提供了几个可重用组件,如原子计数器和集合。原子计数器可以方便实现Redis自增key,而集合可以实现redis key的管理:

原子计数器示例

@Bean 
public RedisAtomicInteger init(RedisConnectionFactory factory) { 
    return new RedisAtomicInteger("myCounter", factory); 
} 
public class Example { 
    @Autowired 
    private RedisAtomicInteger atomicInteger; 

    public void increment() { 
        atomicInteger.incrementAndGet(); 
    } 
} 

Redis 集合示例

@Bean 
public Deque<String> queue(StringRedisTemplate redisTemplate) { 
    return new DefaultRedisList<>(
               redisTemplate.boundListOps("MY_KEY_FOR_QUEUE")); 
}
public class DequeExample { 

    @Resource(name = "queue") 
    private Deque<String> queue; 

    public void add(String value) { 
        queue.add(value); 
    } 

    public String getFirst() { 
        return queue.getFirst(); 
    } 

    public String getLast() { 
        return queue.getLast(); 
    } 
} 

发布/订阅模型

Spring Data Redis 支持基于主题的发布订阅模型:

监听器及主题配置:

@Configuration
public class RedisMessageConfig {
    @Autowired
    private JedisConnectionFactory jedisConnectionFactory;

    @Bean
    RedisMessageListenerContainer redisContainer() {
        RedisMessageListenerContainer container
            = new RedisMessageListenerContainer();
        container.setConnectionFactory(jedisConnectionFactory);
        container.addMessageListener(messageListener(), topic());
        return container;
    }

    @Bean
    MessageListenerAdapter messageListener() {
        return new MessageListenerAdapter(new RedisMessageSubscriber());
    }

    @Bean
    ChannelTopic topic() {
        return new ChannelTopic("messageQueue");
    }
}

实际处理订阅逻辑代码:

@Service
public class RedisMessageSubscriber implements MessageListener {

    public static List<String> messageList = new ArrayList<>();

    @Override
    public void onMessage(Message message, byte[] pattern) {
        messageList.add(message.toString());
        System.out.println("Message received: " + message.toString());
    }
}

发送消息类:

@Service
public class RedisMessagePublisher implements MessagePublisher {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private ChannelTopic topic;

    public RedisMessagePublisher(RedisTemplate<String, Object> redisTemplate, ChannelTopic topic) {
        this.redisTemplate = redisTemplate;
        this.topic = topic;
    }

    @Override
    public void publish(Object message) {
        redisTemplate.convertAndSend(topic.getTopic(), message);
    }
}

总结

本文介绍了redis 及 spring data redis。通过示例展示spring data redis和redis 交互,同时也介绍常用内置组件,实现原子计数器、队列以及订阅/发布模型。

猜你喜欢

转载自blog.csdn.net/neweastsun/article/details/87970540