文章

微服务中使用redis

本文详细介绍了在微服务架构中如何集成Redis,并通过具体示例展示了如何使用Spring Boot进行配置,包括连接池属性设置、不同数据类型如String、Hash、List、Set和SortedSet的操作方法。

微服务中使用redis

文章信息

  • 原文链接:https://jiayq.blog.csdn.net/article/details/107798896
  • 发布时间:2020-08-04 20:49:13
  • 阅读量:2
  • 分类:微服务同时被 3 个专栏收录, 订阅专栏, spring boot, Redis
  • 标签:#微服务中使用redis, #微服务配置redis, #jedis和lettuce, #微服务中redis使用, #如何在微服务中使用redis

摘要

文章浏览阅读2.9k次。本文详细介绍了在微服务架构中如何集成Redis,并通过具体示例展示了如何使用Spring Boot进行配置,包括连接池属性设置、不同数据类型如String、Hash、List、Set和SortedSet的操作方法。


微服务中使用redis

  • 1. 微服务集成redis
  • 2. 配置
  • 3. String
  • 4. Hash
  • 5. List
  • 6. Set
  • 7. Sorted Set

1. 微服务集成redis

image-20200731194539003

2. 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
spring:
  # redis 服务器配置
  redis:
    host: 10.0.228.117
    port: 6379
    password: ""
    timeout: 60000
    database: 0
    # 连接池属性配置
    lettuce:
      pool:
        # 最小空闲连接数
        min-idle: 5
        # 最大空闲连接数
        max-idle: 10
        # 最大活动的连接数
        max-active: 10
        # 连接最大等待数
        max-wait: 3000

spring boos 1.x使用jedis作为redisTemplate的客户端。spring boot 2.x使用lettuce作为redisTemplate的客户端。

Lettuce 和 Jedis 都是Redis的client,所以他们都可以连接 Redis Server。
Jedis在实现上是直接连接的Redis Server,如果在多线程环境下是非线程安全的。
每个线程都去拿自己的 Jedis 实例,当连接数量增多时,资源消耗阶梯式增大,连接成本就较高了。

Lettuce的连接是基于Netty的,Netty 是一个多线程、事件驱动的 I/O 框架。连接实例可以在多个线程间共享,当多线程使用同一连接实例时,是线程安全的。
所以,一个多线程的应用可以使用同一个连接实例,而不用担心并发线程的数量。
当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。

通过异步的方式可以让我们更好的利用系统资源,而不用浪费线程等待网络或磁盘I/O。
所以 Lettuce 可以帮助我们充分利用异步的优势。

在spring boot 2.x。即使application.yaml中配置了spring.redis.jedis.pool....真正用的仍然是letturce。

如果必须要切换,需要在starter中处理。

配置了连接池和服务器的属性,Spring Boot的自动装配机制就会读取这些配置来生成有关Redis的操作对象。自动生成RedisConnectionFactory、RedisTemplate、StringRedisTemplate等常用的Redis操作对象。RedisTemplate会默认使用JdkSerializationRedisSerializer进行序列化,然后存储到Redis中。如果需要在Redis中存储字符串,那么可以使用Spring Boot自动生成的StringRedisTemplate。

1
2
3
4
    @Test
    public void testStringRedisTemplate() {
        stringRedisTemplate.opsForValue().set("string-redis-template", "string-redis-template");
    }

image-20200804183249150

但是StringRedisTemplate只能存储字符串,不能存储对象。

为了解决这个问题,可以通过设置RedisTemplate的序列化器来处理。

  • 首先将原来的config里面的redisTemplate注释掉

image-20200804183931442

  • 然后在application中增加初始化方法

image-20200804184019888

  • 验证

image-20200804184039159

image-20200804184052844

3. String

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@SpringBootTest
public class StringRedisTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void testRedis(){
        redisTemplate.opsForValue().set("int_key", "1");
        System.out.println(redisTemplate.opsForValue().get("int_key"));
        redisTemplate.opsForValue().increment("int_key", 1);
        System.out.println(redisTemplate.opsForValue().get("int_key"));
        redisTemplate.opsForValue().increment("int_key", -1);
        System.out.println(redisTemplate.opsForValue().get("int_key"));
    }

}

image-20200804194555327

4. Hash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@SpringBootTest
public class HashRedisTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void testHashRedis(){
        Map<String, String> map = new LinkedHashMap<>();
        map.put("keys1", "keys1");
        map.put("keys2", "keys2");
        redisTemplate.opsForHash().putAll("hashredis", map);
        System.out.println(redisTemplate.opsForHash().get("hashredis", "keys1"));
        System.out.println(redisTemplate.opsForHash().get("hashredis", "keys2"));

    }

}

image-20200804195238880

image-20200804195248426

5. List

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@SpringBootTest
public class ListRedisTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void testListRedis() {
        redisTemplate.opsForList().leftPushAll("left", "l1", "l2", "l3", "l4", "l5");
        redisTemplate.opsForList().rightPushAll("right", "r1", "r2", "r3", "r4", "r5");
        System.out.println(redisTemplate.opsForList().leftPop("left"));
        System.out.println(redisTemplate.opsForList().rightPop("right"));
        System.out.println("index" + redisTemplate.opsForList().index("left", 3L));
        System.out.println("size of right" + redisTemplate.opsForList().size("right"));
        List list = redisTemplate.opsForList().range("left", 0, -1);
        System.out.println(list);
    }

}

image-20200804200237736

image-20200804200246147

6. Set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@SpringBootTest
public class SetRedisTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void testSetRedis() {

        redisTemplate.opsForSet().add("set1", "s1", "s2", "s3", "s4", "s5");
        redisTemplate.opsForSet().add("set2", "s4", "s5", "s6", "s7", "s8", "s9");
        redisTemplate.opsForSet().add("set1", "tt");
        redisTemplate.opsForSet().remove("set1", "tt");
        System.out.println(redisTemplate.opsForSet().members("set1"));
        System.out.println(redisTemplate.opsForSet().members("set2"));
        System.out.println(redisTemplate.opsForSet().size("set1"));
        System.out.println(redisTemplate.opsForSet().size("set2"));
        // 交集
        System.out.println("交集");
        Set inte = redisTemplate.opsForSet().intersect("set1", "set2");
        System.out.println(inte);
        redisTemplate.opsForSet().intersectAndStore("set1", "set2", "setand");
        System.out.println(redisTemplate.opsForSet().members("setand"));
        // 差集
        // set1 - set2
        System.out.println("set1 - set2");
        Set diff = redisTemplate.opsForSet().difference("set1", "set2");
        System.out.println(diff);
        System.out.println("set2 - set1");
        System.out.println(redisTemplate.opsForSet().difference("set2", "set1"));
        redisTemplate.opsForSet().differenceAndStore("set1", "set2", "setxx1");
        System.out.println(redisTemplate.opsForSet().members("setxx1"));
        redisTemplate.opsForSet().differenceAndStore("set2", "set1", "setxx2");
        System.out.println(redisTemplate.opsForSet().members("setxx2"));
        // 并集
        System.out.println("并集");
        Set union = redisTemplate.opsForSet().union("set1",  "set2");
        redisTemplate.opsForSet().unionAndStore("set1", "set2", "setmm");
        System.out.println(redisTemplate.opsForSet().members("setmm"));
    }

}

image-20200804201838336

image-20200804201902729

7. Sorted Set

有序集合比集合多个分数scope的属性,因此,spring提供了TypedTuple接口用于存储。

image-20200804202321403

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@SpringBootTest
public class SortedSetRedisTests {

    @Autowired
    private RedisTemplate redisTemplate;

    public void testSortedSet() {
        int sum = 1000;
        var dataSet = new HashSet<ZSetOperations.TypedTuple<String>>(sum);
        for(int i = 0;i < sum; i++) {
            dataSet.add(new DefaultTypedTuple<>("value"+i, i/1000.0));
        }
        redisTemplate.opsForZSet().add("zset", dataSet);
        System.out.println("size = " + redisTemplate.opsForZSet().size("zset"));
        redisTemplate.opsForZSet().add("zset", "test", 1.0);
        System.out.println(redisTemplate.opsForZSet().range("zset", -1, -10));
        System.out.println(redisTemplate.opsForZSet().rangeByScore("zset", 0.966, 1.000));
        System.out.println(redisTemplate.opsForZSet().score("zset", "test"));
        redisTemplate.opsForZSet().remove("zset", "test");
        System.out.println(redisTemplate.opsForZSet().rangeWithScores("zset", 0, 10));
        System.out.println(redisTemplate.opsForZSet().reverseRange("zset", 0, 10));
        System.out.println(redisTemplate.opsForZSet().reverseRangeWithScores("zset", 0, 10));
        
    }

}

image-20200804203841450
在这里插入图片描述

本文由作者按照 CC BY 4.0 进行授权