使用redis中setnx保证资源的原子性操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011510825/article/details/81064106

多进程线程)访问共享资源时,能够确保所有其他的进程(线程)都不在同一时间内访问相同的资源。原子操作(atomic operation)是不需要synchronized,这是多线程编程的老生常谈了。所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。


最新有这个业务需求,所以写了个装饰器,保证同一个view同一资源只有一个人有操作权限。talk is cheap, show you the code:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Created by guozhihua12
# 实现对view的锁操作,确保当前的view只有一个人操作
import functools
from redis import RedisCache

redis_cache = RedisCache()


def view_lock():
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # 要求第一个参数为资源的id
            key = 'view_name_{}_id_{}'.format(getattr(func, '__name__'), args[0])
            # 尝试获取锁
            result = redis_cache.setnx(key, '1')
            if result:
                try:
                    data = func(*args, **kwargs)
                except:
                    raise
                finally:
                    # 释放锁
                    redis_cache.delete(key)
                return data
            # todo 考虑是否需要等待两秒后再次尝试获取锁
            raise Exception(message='目前无法操作该资源,稍后再试!')

        return wrapper

    return decorator


@view_lock()
def test(id):
    print(id)


if __name__ == '__main__':
    test(12345)

代码的逻辑比较简单,只要懂点python装饰器原理的同学,理解起来都不难。说下原理,使用的是redis中setnx的属性,如果setnx返回的是1,表示获取锁成功,可以进行相应的view操作;反之,返回0,表示该资源有人正在编辑,无法使用。操作完成后,不管有没异常,都要释放锁。


猜你喜欢

转载自blog.csdn.net/u011510825/article/details/81064106
今日推荐