SpringBoot整合Redis(文末送书)

Redis介绍

Redis 是目前业界使用最广泛的内存数据存储。相比 Mmcached,Redis 支持更丰富的数据结构,例如:字符串类型 string,哈希类型 hash,列表类型 list,集合类型 set,有序集合类型 sortedset等,同时支持数据持久化。除此之外,Redis 还提供一些类数据库的特性,比如事务,HA,主从库。而且Redis具有极高的性能,据官方提供测试数据,50个并发执行100000个请求,读的速度是110000次/s,写的速度是81000次/s ,可以说 Redis 兼具了缓存系统和数据库的一些特性,因此有着丰富的应用场景。
更多Redis介绍和常见操作可以查看我这篇文章:Redis相关知识汇总(下载安装、Redis常见数据类型、持久化、命令和客户端操作)
本文主要讲解SpringBoot整合Redis常见的数据结构。

使用IDEA构建项目,同时引入对应依赖

构建springboot项目引入相关依赖,对应的pom文件内容如下:
PS:快速构建SpringBoot项目可以查看我这篇:SpringBoot快速入门

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot</artifactId>
        <groupId>com.zjq</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zjq</groupId>
    <artifactId>springboot-redis</artifactId>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--lettuce需要添加如下配置-->
        <!--<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>-->

        <!--jedis-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

配置Redis

说明:Spring Boot 1.0 默认使用的是 Jedis 客户端,2.0 替换成 Lettuce,但如果你从 Spring Boot 1.5.X 切换过来,几乎感受不大差异,这是因为 spring-boot-starter-data-redis 为我们隔离了其中的差异性。Lettuce 是一个可伸缩线程安全的 Redis 客户端,多个线程可以共享同一个 RedisConnection,它利用优秀 netty NIO 框架来高效地管理多个连接。
使用Jedis或者Lettuce,yml文件中的redis配置如下:

spring:
  redis:
      # Redis数据库索引(默认为0)
      database: 0
      # Redis服务器地址
      host: 127.0.0.1
      # Redis服务器连接端口
      port: 6379
      # Redis服务器连接密码(默认为空)
      password: 123456
      # jedis连接池配置
#      jedis:
#        pool:
#          #最大连接数 (使用负值表示没有限制) 默认 8
#          max-active: 8
#          #最大阻塞等待时间(负数表示没限制) 默认-1
#          max-wait: -1
#          #最大空闲 默认8
#          max-idle: 8
#          #最小空闲 默认0
#          min-idle: 0
      # lettuce连接池配置
      lettuce:
        pool:
          #最大连接数 默认8
          max-active: 8
          #最大阻塞等待时间(负数表示没限制)
          max-wait: -1
          #最大空闲 默认8
          max-idle: 8
          #最小空闲
          min-idle: 0
      timeout: 100000
server:
  port: 17002

添加Redis序列化方法

SpringBoot 为我们提供了一个高度封装的RedisTemplate类来操作redis的各个命令,开发者无需关心具体的客户端 api 问题,通过RedisTemplate提供的方法,就可以操作redis,方便开发者可以无成本替换 java 客户端。
当我们存储对象的时候,RedisTemplate默认采用的是 Jdk 提供的序列化工具库,该工具有个要求,缓存的对象必须显式实现序列化接口,才能保存。
由于默认的是二进制存储方式,可读性较差,通常情况下,我们会自定义RedisTemplate的序列化策略,采用Jackson将对象转成json,查询的时候将json转成对象。添加如下redis序列化配置:

	/**
	 * 默认是JDK的序列化策略,这里配置redisTemplate采用的是Jackson2JsonRedisSerializer的序列化策略
	 * @param factory
	 * @return
	 */
	@Bean
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
		// 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
		Jackson2JsonRedisSerializer<Object> jacksonSeial = new Jackson2JsonRedisSerializer<>(Object.class);

		// 使用Jackson序列号对象
		ObjectMapper objectMapper = new ObjectMapper();
		// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
		objectMapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
		objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(objectMapper);

		// 使用RedisTemplate对象
		RedisTemplate<String, Object> template = new RedisTemplate<>();
		// 配置连接工厂
		template.setConnectionFactory(factory);
		// 使用StringRedisSerializer来序列化和反序列化redis的key值
		template.setKeySerializer(new StringRedisSerializer());
		// 值采用json序列化
		template.setValueSerializer(jacksonSeial);
		// 使用StringRedisSerializer来序列化和反序列化redis的hash-key值
		template.setHashKeySerializer(new StringRedisSerializer());
		// 值采用json序列化
		template.setHashValueSerializer(jacksonSeial);

		//执行后续方法
		template.afterPropertiesSet();
		return template;
	}

RedisTemplate实操
通过开始的结束我们知道,Redis 提供的数据结构很丰富,支持字符串、哈希表、列表、集合、有序集合等数据类型的存储,RedisTemplate对这五种数据结构分别定义了不同的操作类,具体如下:

  • ValueOperations:操作最简单的K-V数据
  • ListOperations:操作list类型的数据
  • HashOperations:操作hash类型的数据
  • SetOperations:操作set类型的数据
  • ZSetOperations:操作zset类型的数据

心跳检测连接情况

@SpringBootTest
public class RedisApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void redisConnectTest(){
        //心跳检测连接情况
        String pong = redisTemplate.getConnectionFactory().getConnection().ping();
        System.out.println("pong="+pong);
    }

}

存取K-V字符串数据(ValueOperations)

    @Test
    public void redisStringGetSetTest() throws InterruptedException {
        // 设置值,默认不过期
        redisTemplate.opsForValue().set("userName","共饮一杯无");
        // 获取值
        String userName = (String) redisTemplate.opsForValue().get("userName");
        System.out.println("获取userName对应的值="+userName);

        // 设置值并且设置2秒过期时间,过期之后自动删除
        redisTemplate.opsForValue().set("verificationCode", "666888", 2, TimeUnit.SECONDS);
        Thread.sleep(1000);
        System.out.println("获取验证码过期时间(单位秒):" + redisTemplate.getExpire("verificationCode"));
        System.out.println("获取验证码对应的值:" +  redisTemplate.opsForValue().get("verificationCode"));
        Thread.sleep(1000);
        System.out.println("获取验证码对应的值:" +  redisTemplate.opsForValue().get("verificationCode"));

        // 删除key
        Boolean result = redisTemplate.delete("userName");
        System.out.println("删除userName结果:" +  result);
    }

执行结果:
image.png

存取K-V对象数据(ValueOperations)

/**
 * @author zjq
 * @Description:
 */
@Data
@ToString
public class Person{

    private Long id;

    private String name;

    private Integer age;
}
   /**
     * Redis Object类型测试
     * @throws Exception
     */
    @Test
    public void redisObjectTest() throws Exception {
        // 设置对象值,并且2秒自动过期
        Person person = new Person();
        person.setName("共饮一杯无");
        person.setId(1L);
        person.setAge(18);
        savePerson(person);

        //获取对象值
        Person personResult = getPerson(1L);
        System.out.println(personResult.toString());
        System.out.println("获取person过期时间(单位秒):" + redisTemplate.getExpire("person"));


        //删除key
        Boolean deleteValue = redisTemplate.delete("person");
        System.out.println("删除person结果:" +  deleteValue);
    }

    /**
     * 将Person对象存入Redis,键为person:{id},过期时间为2秒
     *
     * @param person 待存储的Person对象
     */
    public void savePerson(Person person) {
        String key = "person:" + person.getId();
        redisTemplate.opsForValue().set(key, person, 2, TimeUnit.HOURS);
    }

    /**
     * 从Redis中获取Person对象,键为person:{id}
     *
     * @param id Person对象的唯一标识符
     * @return 如果存在则返回对应的Person对象,否则返回null
     */
    public Person getPerson(Long id) {
        String key = "person:" + id;
        return (Person) redisTemplate.opsForValue().get(key);
    }

输出结果如下:
image.png

存取hash数据(HashOperations)

HashOperations接口用于操作Redis哈希(Hash data type),提供了一系列方法来处理哈希表中的键值对。

  • 添加、更新、删除键值对
  1. put(K key, HK hashKey, HV value)

在指定key对应的哈希表中,将hashKey与value关联起来。如果已有相同hashKey,则更新其值。

  1. putAll(K key, Map<? extends HK, ? extends HV> m)

将m中的所有键值对批量添加到指定key对应的哈希表中。如果有键已存在,则更新其值。

  1. increment(K key, HK hashKey, long delta)

如果hashKey对应的值是整数类型,将该值增加delta。如果hashKey不存在,则将其设置为delta。

  1. increment(K key, HK hashKey, double delta)

如果hashKey对应的值是浮点数类型,将该值增加delta。如果hashKey不存在,则将其设置为delta。

  1. delete(K key, Object… hashKeys)

从指定key对应的哈希表中删除与给定hashKeys关联的所有键值对。

  • 查询键值对
  1. get(K key, HK hashKey)

返回指定key对应的哈希表中hashKey所关联的值。如果不存在,返回null。

  1. multiGet(K key, Collection hashKeys)

返回指定key对应的哈希表中与给定hashKeys关联的所有值组成的列表。对于不存在的hashKey,对应位置的值为null。

  • 查询哈希表信息
  1. size(K key)

返回指定key对应哈希表中的键值对数量。

  1. keys(K key)

返回指定key对应哈希表中所有hashKey组成的集合。

  1. entries(K key)

返回指定key对应哈希表中所有键值对(Map.Entry<HK, HV>)组成的集合。
存取内容案例如下:
在这里插入图片描述

代码案例:

    /**
     * Redis Hash类型测试
     */
    @Test
    public void redisHashTest() throws Exception {
        // 向hash中添加数据
        HashOperations<String, String, Integer> operations = redisTemplate.opsForHash();
        //Hash 中新增元素。
        operations.put("score", "张三", 2);
        operations.put("score", "李四", 1);
        operations.put("score", "王五", 3);
        operations.put("score", "赵六", 4);

        Boolean hasKey = operations.hasKey("score", "张三");
        System.out.println("检查是否存在【score】【张三】:" + hasKey);
        Integer value = operations.get("score", "张三");
        System.out.println("获取【score】【张三】的值:" + value);
        Set<String> keys = operations.keys("score");
        System.out.println("获取hash表【score】所有的key集合:" + JSON.toJSONString(keys));
        List<Integer> values = operations.values("score");
        System.out.println("获取hash表【score】所有的value集合:" + JSON.toJSONString(values));
        Map<String,Integer> map = operations.entries("score");
        System.out.println("获取hash表【score】下的map数据:" + JSON.toJSONString(map));
        Long delete = operations.delete("score", "李四");
        System.out.println("删除【score】中key为【李四】的数据:" + delete);
        Boolean result = redisTemplate.delete("score");
        System.out.println("删除整个key:" + result);

    }

执行结果:
image.png

存取列表数据(ListOperations)

ListOperations是Spring Data Redis模块中用于操作Redis列表(List data type)的一个核心接口。它提供了丰富的API来执行常见的列表操作,如添加元素、查询元素、删除元素、移动元素等。以下是ListOperations接口中的一些常用方法及其说明:
常用方法:

  • 添加元素
  1. rightPush(K key, V value)

将给定的value值作为新的尾元素添加到指定key对应的列表末尾。

  1. leftPush(K key, V value)

将给定的value值作为新的头元素添加到指定key对应的列表开头。

  1. rightPushAll(K key, V… values)

将一组values依次作为新的尾元素添加到指定key对应的列表末尾。

  1. leftPushAll(K key, V… values)

将一组values依次作为新的头元素添加到指定key对应的列表开头。

  • 查询元素
  1. range(K key, long start, long end)

返回指定key对应列表中索引从start(包含)到end(不包含)之间的元素列表。索引从0开始。

  1. index(K key, long index)

返回指定key对应列表中索引为index的元素。索引从0开始。

  • 删除元素
  1. remove(K key, long index)

删除指定key对应列表中索引为index的元素。索引从0开始。

  1. remove(K key, V value)

删除指定key对应列表中第一个匹配value的元素。

  1. trim(K key, long start, long end)

保留指定key对应列表中索引从start(包含)到end(包含)之间的元素,删除其余元素。

  • 移动元素
  1. rightPopAndLeftPush(K sourceKey, K destinationKey)

从sourceKey对应列表的右侧弹出一个元素,并将其作为左侧元素添加到destinationKey对应列表。如果sourceKey列表为空,则返回null。

  1. leftPopAndRightPush(K sourceKey, K destinationKey)

从sourceKey对应列表的左侧弹出一个元素,并将其作为右侧元素添加到destinationKey对应列表。如果sourceKey列表为空,则返回null。

  • 其他操作
  1. size(K key)

返回指定key对应列表中的元素数量。

  1. leftPop(K key)

从key对应列表的左侧弹出一个元素。如果列表为空,则返回null。

  1. rightPop(K key)

从key对应列表的右侧弹出一个元素。如果列表为空,则返回null。

  1. rightPopAndLeftPush(K sourceKey, K destinationKey, long timeout, TimeUnit unit)

从sourceKey对应列表的右侧弹出一个元素(阻塞最多timeout时间单位的unit),并将其作为左侧元素添加到destinationKey对应列表。如果在等待期间sourceKey列表为空,则返回null。

  1. leftPopAndRightPush(K sourceKey, K destinationKey, long timeout, TimeUnit unit)

从sourceKey对应列表的左侧弹出一个元素(阻塞最多timeout时间单位的unit),并将其作为右侧元素添加到destinationKey对应列表。如果在等待期间sourceKey列表为空,则返回null。

  • 阻塞操作(带超时)
  1. blpop(K… keys, long timeout, TimeUnit unit)

从多个给定keys对应的列表中阻塞地左弹出元素(等待最多timeout时间单位的unit)。返回第一个非空列表的键值对。

  1. brpop(K… keys, long timeout, TimeUnit unit)

从多个给定keys对应的列表中阻塞地右弹出元素(等待最多timeout时间单位的unit)。返回第一个非空列表的键值对。

代码案例:

   /**
     * Redis List类型测试
     */
    @Test
    public void redisListTest() {
        // 向列表中添加数据
        ListOperations<String, Person> operations = redisTemplate.opsForList();
        // 往List左侧插入一个元素
        operations.leftPush("userList", new Person(2,"共饮一杯无",19));
        operations.leftPush("userList", new Person(1,"共饮一杯无",18));
        //往 List 右侧插入一个元素
        operations.rightPush("userList", new Person(3,"共饮一杯无",20));
        operations.rightPush("userList", new Person(4,"共饮一杯无",21));
        // 获取List 大小
        Long size = operations.size("userList");
        System.out.println("获取列表总数:" + size);
        //遍历整个List
        List<Person> allPerson1 = operations.range("userList", 0, size);
        System.out.println("遍历列表所有数据:" + JSON.toJSONString(allPerson1));
        //遍历整个List,-1表示倒数第一个即最后一个
        List<Person> allPerson2 = operations.range("userList", 0, -1);
        System.out.println("遍历列表所有数据:" + JSON.toJSONString(allPerson2));
        //从 List 左侧取出第一个元素,并移除
        Object Person1 = operations.leftPop("userList", 200, TimeUnit.MILLISECONDS);
        System.out.println("从左侧取出第一个元素并移除:" + Person1.toString());
        //从 List 右侧取出第一个元素,并移除
        Object Person2 = operations.rightPop("userList", 200, TimeUnit.MILLISECONDS);
        System.out.println("从右侧取出第一个元素并移除:" + Person2.toString());

    }

执行结果:
image.png

存取Set集合数据(SetOperations)

SetOperations 提供了一组方法,这些方法封装了 Redis Set 数据结构支持的所有核心操作,使得开发者能够轻松地执行添加、移除、查询、计数、交集、并集、差集等操作,而无需直接编写底层的 Redis 命令。它通常作为 RedisTemplate 对象的泛型方法调用结果返回,例如:

SetOperations<String, YourValueType> setOps = redisTemplate.opsForSet();

这里的 YourValueType 是您要存储在 Set 中的具体对象类型。
常用方法
以下是 SetOperations 接口中一些典型的方法及其用途:

  • 基本操作
  1. add(K key, V... values): 将一个或多个成员(values)添加到指定键(key)对应的集合中。如果成员已存在,则不会重复添加。
  2. remove(K key, Object... values): 从指定键(key)对应的集合中移除一个或多个给定的成员。如果成员不存在于集合中,此操作不影响集合。
  3. isMember(K key, Object o): 检查指定键(key)对应的集合中是否包含给定的成员(o)。返回 true 表示存在,false 表示不存在。
  4. members(K key): 返回指定键(key)对应集合中所有的成员。结果以 Set 类型返回,包含了集合内所有对象的完整列表。
  • 集合间操作
  1. difference(K key, K otherKey): 计算指定键(key)对应的集合与其他集合(otherKey)之间的差集,即返回存在于 key 集合但不在 otherKey 集合中的成员。
  2. difference(K key, Collection<K> otherKeys): 计算指定键(key)对应的集合与一组集合(otherKeys)之间的差集,返回存在于 key 集合但不在任何其他集合中的成员。
  3. union(K key, K otherKey): 计算指定键(key)对应的集合与其他集合(otherKey)之间的并集,即返回同时存在于两个集合或仅存在于其中一个集合中的所有成员。
  4. union(K key, Collection<K> otherKeys): 计算指定键(key)对应的集合与一组集合(otherKeys)之间的并集,返回同时存在于 key 集合和其他任意集合或仅存在于任一集合中的所有成员。
  5. intersect(K key, K otherKey): 计算指定键(key)对应的集合与其他集合(otherKey)之间的交集,即返回同时存在于两个集合中的成员。
  6. intersect(K key, Collection<K> otherKeys): 计算指定键(key)对应的集合与一组集合(otherKeys)之间的交集,返回同时存在于 key 集合和其他所有集合中的成员。
  • 额外功能
  1. move(K key, V value, K destKey): 将指定键(key)集合中的某个成员(value)移动到另一个集合(destKey)。如果成功移动,返回 true;否则(如成员不存在或目标集合已存在该成员),返回 false。
  2. pop(K key): 从指定键(key)对应的集合中随机移除并返回一个成员。集合大小减1。
  3. size(K key): 返回指定键(key)对应集合中成员的数量。
  4. randomMember(K key): 随机从指定键(key)对应的集合中返回一个成员,但不移除它。

以上方法涵盖了 Redis 集合类型的主要操作,利用 SetOperations 接口,开发人员可以在 Java 代码中高效、便捷地管理 Redis 集合数据,实现诸如数据存储、查询、统计、合并、过滤等功能,适用于社交网络中的好友关系标签系统唯一性检查等多种应用场景。

代码案例:

    /**
     * Redis Set类型测试
     */
    @Test
    public void redisSetTest() throws Exception {
        // 向集合中添加数据
        SetOperations<String, String> operations = redisTemplate.opsForSet();
        //向集合中添加元素,set元素具有唯一性
        operations.add("city", "北京","上海", "广州", "深圳", "杭州");
        Long size = operations.size("city");
        System.out.println("获取集合总数:" + size);
        //判断是否是集合中的元素
        Boolean isMember = operations.isMember("city", "广州");
        System.out.println("检查集合中是否存在指定元素:" + isMember);
        Set<String> cityNames = operations.members("city");
        System.out.println("获取集合所有元素:" + JSON.toJSONString(cityNames));
        Long remove = operations.remove("city", "广州");
        System.out.println("删除指定元素结果:" + remove);
        //移除并返回集合中的一个随机元素
        String cityName = operations.pop("city");
        System.out.println("移除并返回集合中的一个随机元素:" + cityName);
    }

执行结果:
image.png

存取有序集合数据(ZSetOperations)

ZSetOperations 提供了一组方法,封装了 Redis ZSet 数据结构支持的所有核心操作,包括添加成员、更新分数、按分数范围查询、按排名查询、计算聚合值、执行集合间的有序集合操作等。同样,它通常作为 RedisTemplate 对象的泛型方法调用结果返回:

ZSetOperations<String, YourValueType> zSetOps = redisTemplate.opsForZSet();

这里的 YourValueType 是您要存储在 ZSet 中的具体对象类型。
常用方法
以下是 ZSetOperations 接口中一些典型的方法及其用途:

  • 基本操作
  1. add(K key, V value, double score): 向指定键(key)对应的有序集合中添加一个成员(value),并赋予其指定的分数(score)。如果成员已存在,分数将被更新。
  2. remove(K key, Object... values): 从指定键(key)对应的有序集合中移除一个或多个给定的成员(values)。如果成员不存在于集合中,此操作不影响集合。
  3. score(K key, Object o): 获取指定键(key)对应的有序集合中指定成员(o)的分数。如果成员不存在,返回 null。
  4. rank(K key, Object o): 获取指定键(key)对应的有序集合中指定成员(o)的排名(索引位置)。排名按分数从小到大排列,第一个成员的排名为 0。如果成员不存在,返回 -1。
  5. reverseRank(K key, Object o): 获取指定键(key)对应的有序集合中指定成员(o)的反向排名(按分数从大到小排列)。第一个成员的反向排名为 0。如果成员不存在,返回 -1。
  6. range(K key, long start, long end): 根据排名区间获取指定键(key)对应的有序集合中的成员。返回指定范围内(包括 start 和 end)的成员列表,按分数从小到大排列。
  7. reverseRange(K key, long start, long end): 根据反向排名区间获取指定键(key)对应的有序集合中的成员。返回指定范围内(包括 start 和 end)的成员列表,按分数从大到小排列。
  8. rangeByScore(K key, double min, double max): 根据分数区间获取指定键(key)对应的有序集合中的成员。返回分数在 [min, max] 范围内的成员列表,按分数从小到大排列。
  • 集合间操作
  1. unionAndStore(K key, K otherKey, K destKey): 计算指定键(key)对应的有序集合与其他有序集合(otherKey)之间的并集,并将结果存储到新的有序集合(destKey)。返回并集成员数量。
  2. unionAndStore(K key, Collection<K> otherKeys, K destKey): 计算指定键(key)对应的有序集合与一组有序集合(otherKeys)之间的并集,并将结果存储到新的有序集合(destKey)。返回并集成员数量。
  3. intersectAndStore(K key, K otherKey, K destKey): 计算指定键(key)对应的有序集合与其他有序集合(otherKey)之间的交集,并将结果存储到新的有序集合(destKey)。返回交集成员数量。
  4. intersectAndStore(K key, Collection<K> otherKeys, K destKey): 计算指定键(key)对应的有序集合与一组有序集合(otherKeys)之间的交集,并将结果存储到新的有序集合(destKey)。返回交集成员数量。
  • 额外功能
  1. count(K key, double min, double max): 返回指定键(key)对应的有序集合中,分数在 [min, max] 范围内的成员数量。
  2. incrementScore(K key, V value, double delta): 为指定键(key)对应的有序集合中指定成员(value)的分数增加(或减少,如果 delta 为负数)指定的数值(delta)。
  3. size(K key): 返回指定键(key)对应有序集合中成员的数量。
  4. rangeWithScores(K key, long start, long end): 类似于 range 方法,但除了返回成员列表外,还同时返回每个成员的分数。
  5. reverseRangeWithScores(K key, long start, long end): 类似于 reverseRange 方法,但除了返回成员列表外,还同时返回每个成员的分数。
  6. rangeByScoreWithScores(K key, double min, double max): 类似于 rangeByScore 方法,但除了返回成员列表外,还同时返回每个成员的分数。

与 SetOperations 的差异
SetOperations:

  • 适用于无序、不重复的成员集合。
  • 成员之间没有额外的关联数据,仅凭成员本身进行增删查操作。
  • 不支持分数概念,无法根据特定条件(如分数范围、排名)进行查询或排序。
  • 不支持集合间的并集、交集操作时保留成员的原始顺序或按分数排序的结果。

ZSetOperations:

  • 适用于有序、不重复的成员集合,每个成员关联一个分数。
  • 成员的增删查操作基于成员及其分数进行。
  • 支持根据分数范围、排名(正序或逆序)进行精确查询。
  • 集合间的并集、交集操作可以保留成员的原始顺序(按分数排序),并可将结果存储为新的有序集合。
  • 提供了更新成员分数、获取成员分数、按分数增量调整分数等与分数相关的特有方法。

总结来说,ZSetOperations 在保持成员唯一性的基础上,增加了分数属性和排序功能,提供了更丰富的查询方式和集合间操作,适用于需要对集合元素进行排序、评分、排名等复杂场景,如排行榜带权重的关系存储等。而 SetOperations 则专注于简单、无序的集合管理,适用于需要快速判断成员是否存在、执行集合间基础操作(如并集、交集、差集)等场景。
代码案例:

    /**
     * Redis ZSet类型测试
     */
    @Test
    public void redisZSetTest() throws Exception {
        // 向有序集合中添加数据
        ZSetOperations<String, String> operations = redisTemplate.opsForZSet();
        //向有序集合中添加元素,set元素具有唯一性
        operations.add("userName", "zhangsan", 100);
        operations.add("userName", "lisi", 95);
        operations.add("userName", "wangwu", 75);
        operations.add("userName", "zhaoliu", 85);

        //获取变量指定区间的元素。0, -1表示全部
        Set<String> ranges = operations.range("userName", 0, -1);
        System.out.println("获取有序集合所有元素:" + JSON.toJSONString(ranges));
        Set<String> byScores = operations.rangeByScore("userName", 85, 100);
        System.out.println("获取有序集合所有元素(按分数从小到大):"+ JSON.toJSONString(byScores));
        Long zCard = operations.zCard("userName");
        System.out.println("获取有序集合成员数: " + zCard);
        Long remove = operations.remove("userName", "zhaoliu");
        System.out.println("删除某个成员数结果: " + remove);
        Set<String> ranges1 = operations.range("userName", 0, -1);
        System.out.println("获取有序集合所有元素:" + JSON.toJSONString(ranges1));

    }

执行结果:
在这里插入图片描述

Redis不同数据类型使用场景

本文主要讲解了SpringBoot整合Redis的操作,和RedisTemplate针对不同数据类型的一些场景和说明。总结下每种数据类型都有其独特的特性和适用场景,以下是它们的简要介绍及典型使用场景:

  1. String(字符串)

特性: 最基本的数据类型,可以存储任何类型的数据,包括数字、文本、图片等,支持多种操作如追加、截取、自增等。
使用场景:

  • 计数器:如网页访问计数、点赞数等。
  • 缓存存储:存储简单的键值对数据,如用户会话信息、配置信息等。
  • 发布/订阅通道中的消息标识符。
  1. Hash(哈希)

特性: 存储键值对集合,每个哈希可以存储多个字段-值对,适合存储对象
使用场景:

  • 用户信息存储:存储用户配置、用户资料等,每个字段对应用户的一个属性。
  • Session存储:将用户的会话信息作为一个整体存储。
  • 商品信息存储:每个商品作为一个哈希,包含价格、库存量等多个属性。
  1. List(列表)

特性: 有序的字符串列表,可以在列表两端进行高效的插入和删除操作。
使用场景:

  • 消息队列:实现简单的消息队列系统,新消息可以添加到列表尾部,消费时从头部取出。
  • 最近浏览记录:存储用户最近浏览的商品ID列表。
  • 实现栈或队列数据结构。
  1. Set(集合)

特性: 无序且不重复的字符串集合,支持集合运算如并集、交集、差集等。
使用场景:

  • 好友关系:存储每个用户的好友列表,利用集合间的操作计算共同好友等。
  • 标签系统:为文章或商品分配标签,快速查找拥有相同标签的内容。
  • 去重:如统计网站访问的唯一IP地址。
  1. Sorted Set(有序集合)

特性: 类似集合,但每个成员都关联一个分数,根据分数排序。
使用场景:

  • 排行榜:如游戏得分排行榜,根据分数排序。
  • 时间线:存储带有时间戳的事件,按时间顺序检索。
  • 优先级队列:不仅存储任务,还能根据优先级(分数)进行处理。

这些数据类型的选择取决于具体的应用需求,如数据结构、查询模式、性能要求等。Redis的灵活性使其成为处理多种数据存储和访问模式的理想选择。

书籍推荐

鸟哥的Linux私房菜

《鸟哥的Linux私房菜——服务器架设篇(第三版修订)》是一本不可或缺的Linux服务器架设指导书,适合想要深入学习Linux服务器架设和管理的读者。本书不仅教授如何搭建服务器,还重点关注服务器的安全防护和维护,以及解决常见问题的策略。作者以系统基础和网络基础为起点,深入浅出地介绍了各种常见服务器的搭建方法。无论您是初学者还是有经验的用户,本书都将帮助您掌握Linux服务器的核心知识,为您的服务器提供稳定、安全的运行环境。
在这里插入图片描述

作者介绍

鸟哥,中国台湾成功大学环境工程系博士,就学期间由于研究需要接触到Linux操作系统,又因实验室交接需求而建立“鸟哥的Linux私房菜”网站。因个人喜好“絮叨”,网站文章风格就此成形。曾任中国台湾多家知名Linux教育中心讲师,目前于中国台湾昆山科技大学资讯传播系教授Linux相关课程。专长是Linux操作系统、网站规划与维护、网络安全,兴趣是写作与阅读,研究方向是网络应用整合。

图书内容

本书的章节规划主要分为四篇:第一篇是服务器搭建前的进修专区,第二篇是主机的简易安全防护措施,第三篇是局域网内常见服务器的搭建,第四篇是常见Internet服务器的搭建。前两篇的内容都是关于基础的网络概念和实际网络配置,包括重要的网络自我检测和防火墙设置等。
服务器架设篇,第三版修订,主要是删除了一些过时软件,旧的网站,针对Linux系统版本进行了更新,内容大概有搭建服务器前的准备,网络的基本概念,局域网架构,Linux中常用的网络命令,网络故障排除,主机的安全防护措施,路由,防火墙,DHCP服务器,nfs服务器,nis服务器,ntp服务器,代理服务器,DNS服务器等等。

适合人群

具备一定的Linux基础知识,想进一步深入学习Linux服务器架设和管理的读者。

如何领书

本次本篇文章送书 🔥2本,公众号抽奖1本,累计3本
📆 活动时间:截止到 2024-05-13 10:00:00
🎁抽奖方式:评论区随机抽取2本,公众号抽取1本
🎉参与方式:

  1. 关注博主、点赞、收藏,评论:跟着鸟哥混,一天吃9顿
  2. 关注微信公众号《共饮一杯无》,发送:跟着鸟哥混,即可参与
    或者微信扫描下方图片参与
    在这里插入图片描述

🎉通知方式:活动结束后,会私信中奖粉丝的,各位注意查看私信哦!
也可以通过下方微信名片联系我。

自主购买

小伙伴也可以访问链接进行自主购买哦~
直达京东购买链接🔗:《鸟哥的Linux私房菜:服务器架设篇(第三版修订)》

本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位指出。
主页:共饮一杯无的博客汇总👨‍💻

保持热爱,奔赴下一场山海。🏃🏃🏃

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/601780.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年武汉市工业投资和技术改造及工业智能化改造专项资金申报补贴标准、条件程序和时间

一、申报政策类别 (一)投资和技改补贴。对符合申报条件的工业投资和技术改造项目,依据专项审计报告明确的项目建设有效期(最长不超过两年)内实际完成的生产性设备购置与改造投资的8%,给予最高不超过800万元专项资金支持。 (二)智能化改造补贴。对符合申报条件的智能化改造项目…

互联网产品为什么要搭建会员体系?

李诞曾经说过一句话&#xff1a;每个人都可以讲5分钟脱口秀。这句话换到会员体系里面同样适用&#xff0c;每个人都能聊点会员体系相关的东西。 比如会员体系属于用户运营的范畴&#xff0c;比如怎样用户分层&#xff0c;比如用户标签及CDP、会员积分、会员等级、会员权益和付…

鸿蒙通用组件弹窗简介

鸿蒙通用组件弹窗简介 弹窗----Toast引入ohos.promptAction模块通过点击按钮&#xff0c;模拟弹窗 警告对话框----AlertDialog列表弹窗----ActionSheet选择器弹窗自定义弹窗使用CustomDialog声明一个自定义弹窗在需要使用的地方声明自定义弹窗&#xff0c;完整代码 弹窗----Toa…

Seata之TCC 模式的使用

系列文章目录 文章目录 系列文章目录前言前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能…

【python数据分析基础】—pandas透视表和交叉表

目录 前言一、pivot_table 透视表二、crosstab 交叉表三、实际应用 前言 透视表是excel和其他数据分析软件中一种常见的数据汇总工具。它是根据一个或多个键对数据进行聚合&#xff0c;并根据行和列上的分组键将数据分配到各个矩形区域中。 一、pivot_table 透视表 pivot_tabl…

风与水如何联合优化?基于混合遗传算法的风-水联合优化运行程序代码!

前言 为提高风电场的供电质量同时增加其发电效益,利用储能技术为风电场配置一个蓄能系统是比较重要的解决措施之一。风电的蓄能技术有水力蓄能、压缩空气蓄能、超导磁力蓄能、流体电池组、电解水制氢等&#xff0c;其中水力蓄能是技术较成熟的一种蓄能方式&#xff0c;且小型的…

给网站网页PHP页面设置密码访问代码

将MkEncrypt.php文件上传至你网站根目录下或者同级目录下。 MkEncrypt.php里面添加代码&#xff0c;再将调用代码添加到你需要加密的页进行调用 MkEncrypt(‘123456’);括号里面123456修改成你需要设置的密码。 密码正确才能进去页面&#xff0c;进入后会存下cookies值&…

项目经理【过程】概念

系列文章目录 【引论一】项目管理的意义 【引论二】项目管理的逻辑 【环境】概述 【环境】原则 【环境】任务 【环境】绩效 【人】概述 【人】原则 【人】任务 【人】绩效 【过程】概念 一、过程是什么 1.1 项目管理五大过程组 1.2 五大过程组之间的相互作用 1.3 项目阶段VS过…

《Linux运维总结:ARM架构CPU基于docker-compose一离线部署consul v1.18.1集群工具》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;《Linux运维篇&#xff1a;Linux系统运维指南》 一、部署背景 由于业务系统的特殊性&#xff0c;我们需要面向不通的客户安装我们的业务系统&…

【SpringBoot】-- 监听容器事件、Bean的前后置事件

目录 一、ApplicationContextInitializer 使用 1、自定义类&#xff0c;实现ApplicationContextInitializer接口 2、在META-INF/spring.factories配置文件中配置自定义类 二、ApplicationListener 使用 1、自定义类&#xff0c;实现ApplicationListener接口 2、在META-…

tensorboard子目录运行

tensorboard默认在根目录运行&#xff0c;浏览器访问127.0.0.1:6006打开界面。 如果想在子目录运行&#xff0c;那么可以这么执行 tensorboard --logdir ./logs --path_prefix/app/asd 然后浏览器既可以通过 http://localhost:6006/app/asd/来访问。​​​​​​ 但这么做遇…

HADOOP之YARN详解

目录 一、YARN的简介 1.1 MapReduce 1.x 1.1.1 MapReduce 1.x的角色 1.2 YARN的介绍 1.3 YARN的设计思想 二 YARN的配置 1. mapred-site.xml 2. yarn-site.xml ​编辑 3. hadoop-env.sh 4. 分发到其他节点 5.YARN的服务启停 6. 任务测试 三 YARN的历史日志 1. 历…

JetBrains的多数据库管理和SQL工具DataGrip 2024.1版本在Windows/Linux系统的下载与安装配置

目录 前言一、DataGrip在Windows安装二、DataGrip在Linux安装三、Windows下使用配置四、Linux下使用配置总结 前言 ​ “ DataGrip是一款多数据库管理和SQL工具&#xff0c;适用于不同类型的数据库。它提供了丰富的功能和工具&#xff0c;可以帮助开发人员更高效地管理数据库、…

【Linux网络编程】4.TCP协议、select多路IO转换

目录 TCP协议 TCP通讯时序 三次握手 四次挥手 滑动窗口 测试代码1 测试结果 Address already in use解决方法 批量杀进程 测试代码2 测试结果 测试代码4 测试结果 TCP状态转换 主动发起连接请求端 主动关闭连接请求端 被动接收连接请求端 被动关闭连接请求端…

浅谈自己用过最好用的AI工具概括

个人最经常用的AI工具的其实是Copilot&#xff0c;但是也有别的一些最好用的AI工具&#xff0c;包括&#xff1a; OpenAI GPT-3&#xff1a;这是一个自然语言生成模型&#xff0c;具有强大的语言理解和生成能力。它可以用于各种任务&#xff0c;如文字生成、自动回复和文本摘要…

1984. 学生分数的最小差值C++

给你一个 下标从 0 开始 的整数数组 nums &#xff0c;其中 nums[i] 表示第 i 名学生的分数。另给你一个整数 k 。 从数组中选出任意 k 名学生的分数&#xff0c;使这 k 个分数间 最高分 和 最低分 的 差值 达到 最小化 。 返回可能的 最小差值 。 示例 1&#xff1a; 输入&…

台灯的十大品牌有哪些?十大护眼灯品牌推荐

相信细心的家长已经发现&#xff0c;自家孩子随着步入更高的年级&#xff0c;每天晚上学习的时间也越来越晚了&#xff0c;而这个过程中必然少不了一盏好的台灯&#xff01; 市场上有不少网红代言的护眼灯&#xff0c;虽然它们销售量高&#xff0c;但其实缺乏专业技术和安全保障…

大数据Scala教程从入门到精通第三篇:Scala和Java的关系

一&#xff1a;Scala和Java的关系 1&#xff1a;详解 一般来说&#xff0c;学 Scala的人&#xff0c;都会 Java&#xff0c;而 Scala 是基于 Java 的&#xff0c;因此我们需要将 Scala和 Java 以及 JVM 之间的关系搞清楚&#xff0c;否则学习 Scala 你会蒙圈 Scala可以使用SDK…

【算法】基础算法004之前缀和

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 前言 本篇文章为大家带来前缀和…

推荐一个gpt全能网站

进入后&#xff0c;里面是这样的 点开后&#xff0c;里面是这样的 你以为只有这些吗&#xff1f; 往下翻一翻&#xff0c;你会发现新大陆&#xff01;&#xff01; 在输入框的下面&#xff0c;有一个分类栏&#xff0c;鼠标移上去&#xff0c;下面就会给出一堆网站 光是gp…
最新文章