Skip to main content
 首页 » 数据库

Spring Data Redis 实战

2022年07月19日202pander-it

## 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 交互,同时也介绍常用内置组件,实现原子计数器、队列以及订阅/发布模型。


本文参考链接:https://blog.csdn.net/neweastsun/article/details/87970540