redis并发锁incr

Redis的INCR命令将key中存储的数字值递增。如果key不存在,那么key的值会先被初始化为0,然后在执行INCR操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。本操作的值限制在64位(bit)有符号数字表示之内。 ,,如果您需要使用Redis实现分布式锁,可以使用Redis的SETNX命令。SETNX命令可以将指定的键名和值存储到Redis中,但是仅当该键名不存在时才会执行此操作。如果该键名已经存在,则该命令不会执行任何操作。

Redis并发锁时间怎么设置

在分布式系统中,为了保证数据的一致性和完整性,常常需要使用锁来控制对共享资源的访问,Redis作为一款高性能的键值存储数据库,也可以用来实现分布式锁,本文将介绍如何设置Redis并发锁的时间。

Redis并发锁的基本原理

Redis的并发锁是通过使用SET命令和NX(Not eXists)和PX(Precision-Key)选项来实现的,当一个客户端尝试获取锁时,它会发送一个SET命令,同时指定一个唯一的key和一个过期时间,如果这个key不存在,那么客户端将成功获取锁;如果这个key已经存在,那么客户端将无法获取锁,通过设置过期时间,可以确保锁在一定时间内有效。

设置Redis并发锁的方法

1、使用SET命令和NX选项

import redis
def acquire_lock(conn, lock_name, acquire_timeout=10, lock_timeout=10):
    identifier = str(uuid.uuid4())
    lock_timeout = int(math.ceil(lock_timeout))
    
    end = time.time() + acquire_timeout
    while time.time() < end:
        if conn.set(lock_name, identifier, ex=lock_timeout, nx=True):
            return identifier
        elif not conn.ttl(lock_name):
            conn.expire(lock_name, lock_timeout)
    
    return False

2、使用Lua脚本

import redis
import time
import uuid
def acquire_lock(conn, lock_name, acquire_timeout=10, lock_timeout=10):
    identifier = str(uuid.uuid4())
    lock_timeout = int(math.ceil(lock_timeout))
    lua = """
    local key = KEYS[1]
    local timeout = tonumber(ARGV[1])
    local identifier = tostring(ARGV[2])
    
    local current_time = tonumber(redis.call('TIME'))
    while current_time < math.min(timeout, tonumber(ARGV[3])) do
        if redis.call('GET', key) == false then
            redis.call('SET', key, identifier, 'PX', timeout)
            return identifier
        elseif tonumber(redis.call('TTL', key)) > 0 then
            redis.call('EXPIRE', key, timeout)
            return identifier
        end
        
        table.insert(KEYS, key) -将当前key添加到等待队列中
        table.remove(KEYS, KEYS[1]) -从等待队列中移除当前key
        redis.call('WAIT', math.min(timeout * 1000, tonumber(ARGV[3]))) -等待一段时间后再次尝试获取锁
        redis.call('REMOVE', KEYS[KEYS + 1]) -从等待队列中移除刚刚插入的key
        redis.call('MULTI') -开启事务模式
        redis.call('SET', key, identifier) -将当前key的值设置为identifier
        redis.call('PEXPIRE', key, timeout) -为当前key设置过期时间
        redis.call('EXEC') -执行事务中的命令
        return identifier -如果成功获取锁,返回identifier作为解锁标识符
        end
        redis.call('UNWATCH') -如果当前key已经被其他客户端锁定,取消监视该key的操作
        redis.call('SLEEP', (timeout * 1000) % (10 * 1000)) -让当前客户端等待一段时间后再次尝试获取锁
        redis.call('REDISCALL', 'EVAL', KEYS[1], "if (redis.call('EXISTS', KEYS[1]) == 'nil') then return nil else return me end") -如果当前key已经被删除,返回nil表示无法获取锁
        redis.call('MULTI') -开启事务模式
        redis.call('UNSET', key) -将当前key的值设置为nil
        redis.call('PEXPIRE', key, '-inf') -为当前key设置一个非常小的过期时间,使其立即过期
        redis.call('EXEC') -执行事务中的命令
        return nil -如果无法获取锁,返回nil表示解锁标识符无效
    end"""
    lua_script = conn.register_script(lua)
    lua_result = lua_script(lock_name, lock_timeout * 1000, str(uuid.uuid4()), str(lock_timeout * 1000), str(acquire_timeout * 1000))
    
    if isinstance(lua_result, list) and len(lua_result) == 2:
        return str(lua_result[0]) == str(identifier) or str(lua_result[1]) == 'nil' and acquire_lock(conn, lock_name, acquire_timeout, lock_timeout) is not None
    
    return None if not isinstance(lua_result, list) or len(lua_result) != 2 or not (str(lua_result[0]) == str(identifier) or str(lua_result[1]) == 'nil') else acquire_lock(conn, lock_name, acquire_timeout, lock_timeout) is not None

分享名称:redis并发锁incr
分享路径:http://www.csdahua.cn/qtweb/news29/466729.html

网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网