RedisTemplate 各类型基本使用||分布式锁

SpringDataRedis

官网:https://spring.io/projects/spring-data-redis

提供了对不同 Redis 客户端的整合(Lettuce 和 Jedis),默认是 Lettuce

提供了 RedisTemplate 统一 API 来操作 Redis

支持 Redis 的发布订阅模型

支持 Redis 哨兵和 Redis 集群

支持基于 Lettuce 的响应式编程

支持基于 JDK、JSON、字符串、Spring 对象的数据序列化及反序列化

支持基于 Redis 的 JDKCollection 实现

RedisTemplate

API

返回值类型

说明

redisTemplate.opsForValue()

ValueOperations

操作 String 类型数据

redisTemplate.opsForHash()

HashOperations

操作 Hash 类型数据

redisTemplate.opsForList()

ListOperations

操作 List 类型数据

redisTemplate.opsForSet()

SetOperations

操作 Set 类型数据

redisTemplate.opsForZSet()

ZSetOperations

操作 SortedSet 类型数据

redisTemplate

通用的命令

使用步骤
  1. 引入 spring-boot-starter-data-redis 依赖

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

在 application.yml 配置 Redis 的信息

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
    database: 0 # 几号库
    lettuce:
      pool:
        max-active: 8 # 最大连接
        max-idle: 8 # 最大空闲连接
        min-idle: 0 # 最小空闲连接
        max-wait: 100ms # 连接等待时间

注入 RedisTemplate

@Autowired
private RedisTemplate redisTemplate;
一、RedisTemplate各类型基本操作
package cn.com.easyExcel;

/**
 * @ClassName: RedisDemo各类型操作
 * @Author: ljy
 * @Description:
 * redisTemplate.opsForValue()    ValueOperations    操作 String 类型数据
 * redisTemplate.opsForHash()    HashOperations    操作 Hash 类型数据
 * redisTemplate.opsForList()    ListOperations    操作 List 类型数据
 * redisTemplate.opsForSet()    SetOperations    操作 Set 类型数据
 * redisTemplate.opsForZSet()    ZSetOperations    操作 SortedSet 类型数据
 */

import cn.com.easyExcel.enums.SexEnum;
import cn.com.easyExcel.mapper.UserMapper;
import cn.com.easyExcel.pojo.User;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mysql.cj.util.StringUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

//RedisTemplate使用最详解(三)--- opsForHash()
// https://blog.csdn.net/weixin_43658899/article/details/121063660
@SpringBootTest
public class RedisDemo各类型操作 {

    // 注入 RedisTemplate
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 注入 StringRedisTemplate
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

   /* 1、put(H var1, HK var2, HV var3)
    新增hashMap值
    var1 为Redis的key
    var2 为key对应的map值的key
    var3 为key对应的map值的值
    var2相同替换var3*/
    @Test
    void put() {
        redisTemplate.opsForHash().put("hashValue","map1","value1");
        redisTemplate.opsForHash().put("hashValue","map2","value2");
        redisTemplate.opsForHash().put("hashValue","map2","value3");
        Map map = redisTemplate.opsForHash().entries("hashValue");
        System.err.println(map);
        //{map1=value1, map2=value3}
    }

   /* 2、get(H var1, Object var2)
    获取key对应的map中,key为var2的map的对应的值*/
    @Test
    void get() {
        Object o = redisTemplate.opsForHash().get("hashValue", "map1");
        System.err.println("o = " + o);
        //o = value1
    }

    /*3、entries(H key)
        获取key对应的所有map键值对*/
    @Test
    void entries() {
        Map hashValue = redisTemplate.opsForHash().entries("hashValue");
        System.err.println("hashValue = " + hashValue);
        //hashValue = {map1=value1, map2=value3}
    }

   /* 4、keys(H key)
    获取key对应的map中所有的键*/
    @Test
    void keys() {
        Set hashValue = redisTemplate.opsForHash().keys("hashValue");
        System.err.println("hashValue = " + hashValue);
        //hashValue = [map1, map2]
    }

   /* 5、values(H key)
    获取key对应的map中所有的值*/
   @Test
   void values() {
       List hashValue = redisTemplate.opsForHash().values("hashValue");
       System.out.println("hashValue = " + hashValue);
       //hashValue = [value1, value3]
   }

   /*6、hasKey(H key, Object var2)
    判断key对应的map中是否有指定的键*/
    @Test
    void hasKey() {
        Boolean aBoolean = redisTemplate.opsForHash().hasKey("hashValue", "map1");
        System.out.println("aBoolean = " + aBoolean);
        //aBoolean = true
        /*7、size(H key)
        获取key对应的map的长度*/
        Long hashValue = redisTemplate.opsForHash().size("hashValue");
        System.out.println("hashValue = " + hashValue);
        //hashValue = 2
    }

    /*8、putIfAbsent(H key, HK var2, HV var3)
    如果key对应的map不存在,则新增到map中,存在则不新增也不覆盖*/
    @Test
    void putIfAbsent() {
        redisTemplate.opsForHash().putIfAbsent("hashValue", "map3", "value3");
    }

    /*9、putAll(H key, Map<? extends HK, ? extends HV> map)
    直接以map集合的方式添加key对应的值
    map中key已经存在,覆盖替换
    map中key不存在,新增*/
    @Test
    void putAll() {
        Map newMap = new HashMap();
        newMap.put("map4","map44");
        newMap.put("map5","map55");
        redisTemplate.opsForHash().putAll("hashValue",newMap);

    }

    /*10、multiGet(H key, Collection var2)
    以集合的方式获取这些键对应的map*/
    @Test
    void multiGet() {
        List list = new ArrayList<>();
        list.add("map1");
        list.add("map2");
        List hashValue = redisTemplate.opsForHash().multiGet("hashValue", list);
        System.out.println("hashValue = " + hashValue);
        //hashValue = [value1, value3]
    }

    /*11、lengthOfValue(H key, HK var2)
    获取指定key对应的map集合中,指定键对应的值的长度*/
    @Test
    void lengthOfValue() {
        Long aLong = redisTemplate.opsForHash().lengthOfValue("hashValue", "map1");
        System.out.println("aLong = " + aLong);
        //aLong = 6
    }

    /*12、increment(H key, HK var2, long long1)
   使key对应的map中,键var2对应的值以long1自增*/
    @Test
    void increment() {
        Long increment = redisTemplate.opsForHash().increment("hashValue", "map7", 1);
        System.err.println("increment = " + increment);
        //increment = 1

        /*13、increment(H key, HK var2, double d1)
        使key对应的map中,键var2对应的值以double类型d1自增*/
        Double increment1 = redisTemplate.opsForHash().increment("hashValue", "map8", 1.2);
        System.err.println("increment = " + increment1);

    }
    /*14、scan(H var1, ScanOptions var2)
    匹配获取键值对
    ScanOptions.NONE为获取全部键对
    ScanOptions.scanOptions().match(“map1”).build(),匹配获取键位map1的键值对,不能模糊匹配*/
    @Test
    void scan() {
        Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan("hashValue", ScanOptions.scanOptions().match("map1").build());
        //Cursor<Map.Entry<Object,Object>> cursor = redisTemplate.opsForHash().scan("hashValue",ScanOptions.NONE);
        while (cursor.hasNext()) {
            Map.Entry<Object, Object> entry = cursor.next();
            System.out.println("entry.getKey() = " + entry.getKey());
            System.out.println("entry.getValue() = " + entry.getValue());
        }
    }

   /* 15、delete(H key, Object… var2)
    删除key对应的map中的键值对*/
        @Test
        void deleted () {
            Long delete = redisTemplate.opsForHash().delete("hashValue", "map1", "map2");
            System.out.println("delete = " + delete);
            //map1和map2被删除
        }

    /*16、拓展
    map中存储对象、对象集合时最好转为JSON字符串,容易解析
    map中键值对都可以存为对象、对象集合JSON字符串,具体看实际应用存储*/
    @Autowired
    private UserMapper userMapper;
    @Test
    void toJSONString() {
        //查询用户名包含a,年龄在20到30之间,邮箱信息不为null的用户信息 会排除逻辑删除项
        //SELECT id,user_name AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0
        // AND (user_name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .between("age", 1, 30)
                .isNotNull("email");
        List<User> list = userMapper.selectList(queryWrapper);
        redisTemplate.opsForHash().put("hashValue", JSON.toJSONString(list), JSON.toJSONString(list));

    }


   

    @Test
    void setSaveUsertoJSONString() {
        User user = new User(16L, "小苗", 99, "99QQ", SexEnum.FEMALE);
        // 序列化
        stringRedisTemplate.opsForValue().set("user99", JSON.toJSONString(user));
        String user1 = stringRedisTemplate.opsForValue().get("user99");
        // 反序列化
        User user2 = JSON.parseObject(user1, User.class);
        System.out.println(user2);
        //User(id=16, name=小苗, age=99, email=99QQ, sex=null, isDeleted=1)
    }
}

二、RedisTemplate各类型基本操作+赋值

@SpringBootTest
public class RedisDemo各类型赋值 {

    // 注入 RedisTemplate
    @Autowired
    private RedisTemplate redisTemplate;
    // 注入 StringRedisTemplate
    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    // String 类型
    @Test
    void testString () {
        redisTemplate.opsForValue().set("name", "xiaobai");
        Object name = redisTemplate.opsForValue().get("name");
        System.err.println(name);
        //xiaobai
    }

    // Hash 类型
    @Test
    public void testHash () {
        Set<String> sets = new HashSet<>();
        sets.add("张三");
        sets.add("李四");
        sets.add("王五");
        sets.add("赵六");
        System.out.println(sets);
        redisTemplate.opsForHash().put("user1", "name", "clarence");
        redisTemplate.opsForHash().put("user1", "age", "25");
        redisTemplate.opsForHash().put("user1", "age", "28");
        redisTemplate.opsForHash().put("user1", "set", sets);
        Map map = redisTemplate.opsForHash().entries("user1");
        System.err.println(map);
        //{name=clarence, age=28}
        //具体参考各类型操作
        boolean a = redisTemplate.opsForHash().putIfAbsent("user8", "name", sets);
        redisTemplate.opsForHash().put("user1", "name", sets);
        //设置hash类型过期时间  只能设置 key 不设置 hashKey
        boolean c = redisTemplate.expire("user1", 20, TimeUnit.SECONDS);
    }

    // List 类型
    @Test
    public void testList () {
        redisTemplate.opsForList().leftPushAll("names", "xiaobai", "xiaohei", "xiaolan");
        List<String> names = redisTemplate.opsForList().range("names", 0, 3);
        System.err.println(names);
        //[xiaolan, xiaohei, xiaobai]
    }

    // Set 类型
    @Test
    public void testSet () {
        redisTemplate.opsForSet().add("set", "a", "b", "c");
        Set<String> set = redisTemplate.opsForSet().members("set");
        System.err.println(set);
        //[c, b, a]
    }

    // SortedSet 类型
    @Test
    public void testSortedSet () {
        redisTemplate.opsForZSet().add("class", "xiaobai", 90);
        Set aClass = redisTemplate.opsForZSet().rangeByScore("class", 90, 100);
        System.err.println(aClass);
        //[xiaobai]
        Set<ZSetOperations.TypedTuple<String>> set = new HashSet<>();
        set.add(new DefaultTypedTuple<>("xiaohei", 88.0));
        set.add(new DefaultTypedTuple<>("xiaohui", 94.0));
        set.add(new DefaultTypedTuple<>("xiaolan", 84.0));
        set.add(new DefaultTypedTuple<>("xiaolv", 82.0));
        set.add(new DefaultTypedTuple<>("xiaohong", 99.0));
        redisTemplate.opsForZSet().add("class", set);
        Set aClass1 = redisTemplate.opsForZSet().range("class", 0, 6);
        System.err.println(aClass1);
        //[xiaolv, xiaolan, xiaohei, xiaobai, xiaohui, xiaohong]
    }

    @Test
    public void setTimeout() {
        //向redis里存入数据和设置缓存时间
        stringRedisTemplate.opsForValue().set("baike", "100", 60 * 10, TimeUnit.SECONDS);
        //向redis里存入数据和设置缓存时间 ,10秒就过期了,过期就会自动删除
        stringRedisTemplate.opsForValue().set("test", "100", 10, TimeUnit.SECONDS);
        //val做-1操作
        Long baike = stringRedisTemplate.boundValueOps("baike").increment(-1);
        //根据key获取缓存中的val
        String baike1 = stringRedisTemplate.opsForValue().get("baike");
        //val +1
        Long baike2 = stringRedisTemplate.boundValueOps("baike").increment(1);
        //根据key获取过期时间
        Long baike3 = stringRedisTemplate.getExpire("baike");
        //根据key获取过期时间并换算成指定单位
        Long baike4 = stringRedisTemplate.getExpire("baike", TimeUnit.SECONDS);
        //根据key删除缓存
        Boolean baike5 = stringRedisTemplate.delete("baike");
        //检查key是否存在,返回boolean值
        Boolean aBoolean = stringRedisTemplate.hasKey("baike");
        //向指定key中存放set集合
        stringRedisTemplate.opsForSet().add("baike", "1", "2", "3");
        //设置过期时间
        Boolean aBoolean1 = stringRedisTemplate.expire("baike", 1000, TimeUnit.MILLISECONDS);
        //根据key查看集合中是否存在指定数据
        Boolean member = stringRedisTemplate.opsForSet().isMember("baike", "1");
        //根据key获取set集合
        Set<String> set = stringRedisTemplate.opsForSet().members("baike");
        //验证有效时间
        Long expire = redisTemplate.boundHashOps("baike").getExpire();
        /**
         * 从redis中获取key对应的过期时间;
         * 如果该值有过期时间,就返回相应的过期时间;
         * 如果该值没有设置过期时间,就返回-1;
         * 如果没有该值,就返回-2;
         */
        Long key的名称 = redisTemplate.opsForValue().getOperations().getExpire("key的名称");
    }
}

三、分布式锁的实现

 /**
     * 17、分布式锁的实现:解决的问题就是需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题
     */
    @Test
    public void test() {
        redisTemplate.opsForValue().set("num", 0);
    }
    @Test
    void setLock(){
//        UUID防止误删
        String uuid=String.valueOf(UUID.randomUUID());
        //1获取锁,setne
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid,20, TimeUnit.SECONDS);
        //2获取锁成功,查询num的值
        if (lock) {
            Object value = redisTemplate.opsForValue().get("num");
            //2.1判断num为空return
            if (Objects.isNull(value) ) {
                return;
            }
            //2.2有值就转成int
            int num = Integer.parseInt(value + "");
            //2.3吧Redis的num加1
            redisTemplate.opsForValue().set("num", ++num);
            //2.4释放锁,del
            String lockuuid = (String) redisTemplate.opsForValue().get("lock");
            if(uuid.equals(lockuuid)){
                redisTemplate.delete("lock");
            }

        } else {
            //获取锁失败,每隔0.1秒再获取
            try {
                Thread.sleep(100);
                setLock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值