封装redis 分布式锁 RedisCallback

这篇具有很好参考价值的文章主要介绍了封装redis 分布式锁 RedisCallback。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        RedisCallback 是redis 一个回调接口,在 Redis 连接后执行单个命令,返回执行命令后的结果。  如果在使用 RedisCallback 时,需要自动获取 Redis 连接资源,使用完毕后并释放连接资源。

        RedisTemplate 类提供了一个 execute 方法,用于执行 Redis 命令并返回执行命令后的结果。文章来源地址https://www.toymoban.com/news/detail-673296.html

1.lock类方法封装的方法:

package com.ecarx.check.redis;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 类描述 <p>
 * Copyright: Copyright © 2021 ECARX Co., Ltd. All Rights Reserved. <p>
 * Company: xxx科技有限公司<p>
 *
 * @author qb
 * @since 2023/8/30 14:34
 */
@Slf4j
@Component
public class RedisLock {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 释放锁脚本,原子操作,lua脚本
     */
    private static final String UNLOCK_LUA;
    /**
     * 默认过期时间(30ms)
     */
    private static final long DEFAULT_EXPIRE = 30L;

    static {
        StringBuilder sb = new StringBuilder();
        sb.append("if redis.call(\"get\",KEYS[1]) == ARGV[1] ");
        sb.append("then ");
        sb.append("    return redis.call(\"del\",KEYS[1]) ");
        sb.append("else ");
        sb.append("    return 0 ");
        sb.append("end ");
        UNLOCK_LUA = sb.toString();
    }

    /**
     * 获取分布式锁,原子操作
     * @param lockKey   锁
     * @param lockValue 唯一ID, 可以使用UUID.randomUUID().toString();
     * @return 是否枷锁成功
     */
    public boolean lock(String lockKey, String lockValue) {
        return this.lock(lockKey, lockValue, DEFAULT_EXPIRE, TimeUnit.MILLISECONDS);
    }

    /**
     * 获取分布式锁,原子操作
     * @param lockKey   锁
     * @param lockValue 唯一ID, 可以使用UUID.randomUUID().toString();
     * @param expire    过期时间
     * @param timeUnit  时间单位
     * @return 是否枷锁成功
     */
    public boolean lock(String lockKey, String lockValue, long expire, TimeUnit timeUnit) {
        try {
            RedisCallback callback = (connection) -> connection.set(lockKey.getBytes(StandardCharsets.UTF_8),
                    lockValue.getBytes(StandardCharsets.UTF_8), Expiration.seconds(timeUnit.toSeconds(expire)),
                    RedisStringCommands.SetOption.SET_IF_ABSENT);
            return (boolean) redisTemplate.execute(callback);
        } catch (Exception e) {
            log.error("redis lock error ,lock key: {}, value : {}, error info : {}", lockKey, lockValue, e);
        }
        return false;
    }

    /**
     * 释放锁
     * @param lockKey   锁
     * @param lockValue 唯一ID
     * @return 执行结果
     */
    public boolean unlock(String lockKey, String lockValue) {
        RedisCallback callback = (connection) -> connection.eval(UNLOCK_LUA.getBytes(), ReturnType.BOOLEAN, 1, lockKey.getBytes(StandardCharsets.UTF_8), lockValue.getBytes(StandardCharsets.UTF_8));
        return (boolean) redisTemplate.execute(callback);
    }

    /**
     * 获取Redis锁的value值
     * @param lockKey 锁
     */
    public String get(String lockKey) {
        try {
            RedisCallback callback = (connection) -> new String(Objects.requireNonNull(connection.get(lockKey.getBytes())), StandardCharsets.UTF_8);
            return (String) redisTemplate.execute(callback);
        } catch (Exception e) {
            log.error("get redis value occurred an exception,the key is {}, error is {}", lockKey, e);
        }
        return null;
    }

    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return Boolean.TRUE.equals(redisTemplate.hasKey(key));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return false;
        }
    }
}

2.使用分布式锁

String taskId = "123456";
 for (int i = 0; i < 20; i++) {
    boolean check = redisLock.lock("CHECK_MM_FINISH_BATCH_" + taskId, uuid, 60, TimeUnit.SECONDS);
    if (check) {
            try {
               /*
               * 业务逻辑处理
               */
            } finally {
                // 释放锁
                redisLock.unlock("CHECK_MDB_FINISH_BATCH_" + taskId, uuid);
                log.info("释放锁, 服务:taskId:{}", taskId);
            }
             break;
            } else {
                log.info("更新完成状态抢锁失败, taskId:{}, batchId:{}", taskId, batchId);
                // 每次循环延迟三秒
                Thread.sleep(3000);
            }
}

到了这里,关于封装redis 分布式锁 RedisCallback的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 分布式系统面试全集通第一篇(dubbo+redis+zookeeper----分布式+CAP+BASE+分布式事务+分布式锁)

    什么是分布式 一个系统各组件分别部署在不同服务器。彼此通过网络通信和协调的系统。 也可以指多个不同组件分布在网络上互相协作,比如说电商网站 也可以一个组件的多个副本组成集群,互相协作如同一个组件,比如数据存储服务中为了数据不丢失而采取的多个服务备

    2024年04月11日
    浏览(50)
  • 分布式Redis详解

    Redis我们最近学习必备工具之一了, 接下来我们将讲解Redis的简单应用 ,以及相关原理 第一种: 在Linux上安装Redis yum -y install redis 启动Redis redis-server /etc/redis.conf 链接Redis redis-cli 出现这个说明链接成功了 简单的读和取数据 设置远程链接 将redis的配置文件下载到本地: 配置文件是

    2024年02月13日
    浏览(37)
  • [Redis 分布式锁 ]

    目录 前言:   使用场景: 基于 Redis 实现分布式锁的详细示例: 使用示例: 依赖: Redis分布式锁控制并发访问:    记录一些小笔记 , 如果对你有帮助 那就更好了 Redis 实现分布式锁的使用场景包括: 防止重复操作:在分布式环境下,多个进程可能同时对同一个资源进行操作,

    2024年02月08日
    浏览(43)
  • Redis 分布式缓存

    单点 Redis 的问题及解决 数据丢失:实现Redis数据持久化 并发能力:搭建主从集群,实现读写分离 存储能力:搭建分片集群,利用插槽机制实现动态扩容 故障恢复能力:利用哨兵机制,实现健康检测和自动恢复 RDB RDB全称Redis Database Backup file (Redis数据备份文件),也被叫做

    2024年02月10日
    浏览(52)
  • Redis分布式缓存

    -- 基于Redis集群解决单机Redis存在的问题 单机的Redis存在四大问题: Redis有两种持久化方案: RDB持久化 AOF持久化        RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做 Redis数据快照 。简单来说就是把 内存中的所有数据都记录到磁盘 中。当Redis实例故障重启后,

    2024年02月12日
    浏览(52)
  • Redis分布式问题

      Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争关系Redis中可以使用SETNX命令实现分布式锁。当且仅当 key 不存在,将 key 的值设为 value。 若给定的 key 已经存在,则SETNX 不做任何动作SETNX 是『SET if Not eXists』(如果不

    2024年02月09日
    浏览(36)
  • redis与分布式

    主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master),后者称为从节点(Slave),数据的复制是单向的,只能由主节点到从节点。Master以写为主,Slave 以读为主(只读模式),当主节点关闭后,从节点依然可以读取数据,但是会报错 优点 :

    2024年02月12日
    浏览(37)
  • Redis 分布式锁

    在一个分布式的系统中,也会涉及到多个节点访问同一个公共资源的情况。此时就需要通过锁来做互斥控制,避免出现类似于“线程安全”的问题。 而 java 的 synchronized 或者 C++ 的 std::mutex,这样的锁都是只能在当前进程中生效,在分布式的这种多个进程多个主机的场景下就无

    2024年02月21日
    浏览(28)
  • Redis-分布式锁!

    分布式锁,顾名思义,分布式锁就是分布式场景下的锁,比如多台不同机器上的进程,去竞争同一项资源,就是分布式锁。 互斥性:锁的目的是获取资源的使用权,所以只让一个竞争者持有锁,这一点要尽可能保证; 安全性:避免锁因为异常永远不被释放。当一个竞争者在持有

    2024年02月12日
    浏览(38)
  • Redis+分布式+秒杀

    关于mysql关系型数据库的一些分析: 1、从性能上:如果查询结果不是很频繁变动的SQL语句,我们就没有必要每次都去查询数据库,可以把这种数据放在基于缓存的数据库中,这样不仅提升了查询效率还分担了数据库压力。 2、从并发上:在大并发的情况下(比如618秒杀活动,

    2024年02月06日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包