IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Redis分布式锁 -> 正文阅读

[大数据]Redis分布式锁

一般来说,在对数据进行“加锁”时,程序首先需要通过获取(acquire)锁来得到对数据进行排他性访问的能力,然后才能对数据执行一系列操作,最后还要将锁释放(release)给其他程序。对于能够被多个线程访问的共享内存数据结构(shared-memory data structure)来说,这种“先获取锁,然后执行操作,最后释放锁”的动作非常常见。Redis使用WATCH命令来代替对数据进行加锁,因为WATCH只会在数据被其他客户端抢先修改了的情况下通知执行了这个命令的客户端,而不会阻止其他客户端对数据进行修改,所以这个命令被称为乐观锁(optimistic lock)。

分布式锁也有类似的“首先获取锁,然后执行操作,最后释放锁”动作,但这种锁既不是给同一个进程中的多个线程使用,也不是给同一台机器上的多个进程使用,而是由不同机器上的不同Redis客户端进行获取和释放的。何时使用以及是否使用WATCH或者锁取决于给定的应用程序:有的应用不需要使用锁就可以正确地运行,而有的应用只需要使用少量的锁,还有的应用需要在每个步骤都使用锁,不一而足。
分布式锁在业务中非常常见,能够避免在分布式环境中同时对同一个数据进行操作,进而可以避免并发问题。

锁出现不正确行为的原因,以及锁在不正确运行时的症状

  1. 持有锁的进程因为操作时间过长而导致锁被自动释放,但进程本身并不知晓这一点,甚至还可能会错误地释放掉了其他进程持有的锁;
  2. 一个持有锁并打算执行长时间操作的进程已经崩溃,但其他想要获取锁的进程不知道哪个进程持有着锁,也无法检测出持有锁的进程已经崩溃,只能白白地浪费时间等待锁被释放;
  3. 在一个进程持有的锁过期之后,其他多个进程同时尝试去获取锁,并且都获得了锁;
  4. 上面提到的第一种情况和第三种情况同时出现,导致有多个进程获得了锁,而每个进程都以为自己是唯一一个获得锁的进程。
// io-redis 获取redis所有key
async getKeys(match, count = 100) {
    const { app: { redis }, ctx: { helper: { _ } } } = this;

    let keys = [];
    const scanStream = await redis.scanStream({ match, count });
    const result = await new Promise(resolve => {
        scanStream.on('data', data => {
            keys = keys.concat(data);
        });
        scanStream.on('end', () => {
            resolve(_.uniq(keys));
        });
    });

    return result;
}
// 获取redis所有key
async getKeys(pattern, count = 100) {
    const { app: { redis }, ctx: { helper: { _ } } } = this;

    let result = [];
    const _getKeys = async (cursor = 0) => {
        // redis scan迭代获取,默认取100
        const apiResult = await redis.scan(cursor, 'match', pattern, 'count', count);
        result = result.concat(apiResult[1]);

        // 新游标返回0则表示迭代已结束
        if (Number(apiResult[0]) === 0) {
            return;
        }

        // 继续迭代
        await _getKeys(apiResult[0]);
    }

    await _getKeys();

    // 去重
    return _.uniq(result);
}
// redis获取锁
async lock(key, count) {
    const { app: { redis }, config: { cacheKey } } = this;
    const result = await redis.set(key, count, 'EX', cacheKey.lock.expireTime, 'NX');
    return result === 'OK';
}
// redis释放锁
async unlock(key, count) {
    const { app: { redis } } = this;
    const script = `
        if
            redis.call('get', KEYS[1]) == ARGV[1]
        then
            return redis.call('del', KEYS[1])
        else
            return 0
        end
    `;
    const result = await redis.eval(script, 1, key, count);
    return Boolean(result);
}
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-11-14 21:47:10  更:2021-11-14 21:47:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:00:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码