Python的namedtuple使用详解_kongxx的专栏-CSDN博客_namedtuple https://blog.csdn.net/kongxx/article/details/51553362

redlock-py/__init__.py at master · SPSCommerce/redlock-py https://github.com/SPSCommerce/redlock-py/blob/master/redlock/__init__.py

Lock = namedtuple("Lock", ("validity", "resource", "key"))
 
import logging
import string
import random
import time
from collections import namedtuple

import redis
from redis.exceptions import RedisError

# Python 3 compatibility
string_type = getattr(__builtins__, 'basestring', str)

try:
basestring
except NameError:
basestring = str

Lock = namedtuple("Lock", ("validity", "resource", "key"))

class CannotObtainLock(Exception):
pass

class MultipleRedlockException(Exception):
def __init__(self, errors, *args, **kwargs):
super(MultipleRedlockException, self).__init__(*args, **kwargs)
self.errors = errors

def __str__(self):
return ' :: '.join([str(e) for e in self.errors])

def __repr__(self):
return self.__str__()

class Redlock(object):
default_retry_count = 3
default_retry_delay = 0.2
clock_drift_factor = 0.01
unlock_script = """
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end"""

def __init__(self, connection_list, retry_count=None, retry_delay=None):
self.servers = []
for connection_info in connection_list:
try:
if isinstance(connection_info, string_type):
server = redis.StrictRedis.from_url(connection_info)
elif type(connection_info) == dict:
server = redis.StrictRedis(**connection_info)
else:
server = connection_info
self.servers.append(server)
except Exception as e:
raise Warning(str(e))
self.quorum = (len(connection_list) // 2) + 1

if len(self.servers) < self.quorum:
raise CannotObtainLock(
"Failed to connect to the majority of redis servers")
self.retry_count = retry_count or self.default_retry_count
self.retry_delay = retry_delay or self.default_retry_delay

def lock_instance(self, server, resource, val, ttl):
try:
assert isinstance(ttl, int), 'ttl {} is not an integer'.format(ttl)
except AssertionError as e:
raise ValueError(str(e))
return server.set(resource, val, nx=True, px=ttl)

def unlock_instance(self, server, resource, val):
try:
server.eval(self.unlock_script, 1, resource, val)
except Exception as e:
logging.exception("Error unlocking resource %s in server %s", resource, str(server))

def get_unique_id(self):
CHARACTERS = string.ascii_letters + string.digits
return ''.join(random.choice(CHARACTERS) for _ in range(22)).encode()

def lock(self, resource, ttl):
retry = 0
val = self.get_unique_id()

# Add 2 milliseconds to the drift to account for Redis expires
# precision, which is 1 millisecond, plus 1 millisecond min
# drift for small TTLs.
drift = int(ttl * self.clock_drift_factor) + 2

redis_errors = list()
while retry < self.retry_count:
n = 0
start_time = int(time.time() * 1000)
del redis_errors[:]
for server in self.servers:
try:
if self.lock_instance(server, resource, val, ttl):
n += 1
except RedisError as e:
redis_errors.append(e)
elapsed_time = int(time.time() * 1000) - start_time
validity = int(ttl - elapsed_time - drift)
if validity > 0 and n >= self.quorum:
if redis_errors:
raise MultipleRedlockException(redis_errors)
return Lock(validity, resource, val)
else:
for server in self.servers:
try:
self.unlock_instance(server, resource, val)
except:
pass
retry += 1
time.sleep(self.retry_delay)
return False

def unlock(self, lock):
redis_errors = []
for server in self.servers:
try:
self.unlock_instance(server, lock.resource, lock.key)
except RedisError as e:
redis_errors.append(e)
if redis_errors:
raise MultipleRedlockException(redis_errors)

import loggingimport stringimport randomimport timefrom collections import namedtuple
import redisfrom redis.exceptions import RedisError
# Python 3 compatibilitystring_type = getattr(__builtins__, 'basestring', str)
try:    basestringexcept NameError:    basestring = str

Lock = namedtuple("Lock", ("validity", "resource", "key"))

class CannotObtainLock(Exception):    pass

class MultipleRedlockException(Exception):    def __init__(self, errors, *args, **kwargs):        super(MultipleRedlockException, self).__init__(*args, **kwargs)        self.errors = errors
    def __str__(self):        return ' :: '.join([str(e) for e in self.errors])
    def __repr__(self):        return self.__str__()

class Redlock(object):
    default_retry_count = 3    default_retry_delay = 0.2    clock_drift_factor = 0.01    unlock_script = """    if redis.call("get",KEYS[1]) == ARGV[1] then        return redis.call("del",KEYS[1])    else        return 0    end"""
    def __init__(self, connection_list, retry_count=None, retry_delay=None):        self.servers = []        for connection_info in connection_list:            try:                if isinstance(connection_info, string_type):                    server = redis.StrictRedis.from_url(connection_info)                elif type(connection_info) == dict:                    server = redis.StrictRedis(**connection_info)                else:                    server = connection_info                self.servers.append(server)            except Exception as e:                raise Warning(str(e))        self.quorum = (len(connection_list) // 2) + 1
        if len(self.servers) < self.quorum:            raise CannotObtainLock(                "Failed to connect to the majority of redis servers")        self.retry_count = retry_count or self.default_retry_count        self.retry_delay = retry_delay or self.default_retry_delay
    def lock_instance(self, server, resource, val, ttl):        try:            assert isinstance(ttl, int), 'ttl {} is not an integer'.format(ttl)        except AssertionError as e:            raise ValueError(str(e))        return server.set(resource, val, nx=True, px=ttl)
    def unlock_instance(self, server, resource, val):        try:            server.eval(self.unlock_script, 1, resource, val)        except Exception as e:            logging.exception("Error unlocking resource %s in server %s", resource, str(server))
    def get_unique_id(self):        CHARACTERS = string.ascii_letters + string.digits        return ''.join(random.choice(CHARACTERS) for _ in range(22)).encode()
    def lock(self, resource, ttl):        retry = 0        val = self.get_unique_id()
        # Add 2 milliseconds to the drift to account for Redis expires        # precision, which is 1 millisecond, plus 1 millisecond min        # drift for small TTLs.        drift = int(ttl * self.clock_drift_factor) + 2
        redis_errors = list()        while retry < self.retry_count:            n = 0            start_time = int(time.time() * 1000)            del redis_errors[:]            for server in self.servers:                try:                    if self.lock_instance(server, resource, val, ttl):                        n += 1                except RedisError as e:                    redis_errors.append(e)            elapsed_time = int(time.time() * 1000) - start_time            validity = int(ttl - elapsed_time - drift)            if validity > 0 and n >= self.quorum:                if redis_errors:                    raise MultipleRedlockException(redis_errors)                return Lock(validity, resource, val)            else:                for server in self.servers:                    try:                        self.unlock_instance(server, resource, val)                    except:                        pass                retry += 1                time.sleep(self.retry_delay)        return False
    def unlock(self, lock):        redis_errors = []        for server in self.servers:            try:                self.unlock_instance(server, lock.resource, lock.key)            except RedisError as e:                redis_errors.append(e)        if redis_errors:            raise MultipleRedlockException(redis_errors)

最新文章

  1. webstorm官网最新版激活:
  2. EndNote(二)之英文引文导入方式
  3. Quartz-2D
  4. selenium源码分析-webdriver(二)
  5. 后缀数组 SPOJ 694 Distinct Substrings
  6. SpringMVC4 + Spring + MyBatis3 基于注解的最简配置
  7. oracle学习系列之三 (约束)
  8. Linux守护进程详解(init.d和xinetd) [转]
  9. 14.6.8 Configuring the InnoDB Master Thread IO Rate 配置InnoDB 主线程IO 速率:
  10. MVC部署出现HTTP 404 错误
  11. [C++程序设计]返回指针值的函数
  12. HTTP 返回状态值详解
  13. iOS-swift-基础篇1
  14. 201521044091《Java程序设计》第7周学习总结
  15. BZOJ 3473 字符串
  16. NRF52832与W25Q80通信
  17. django 配置邮件发送 send_email
  18. Mysql 5.7 CentOS 7 安装MHA
  19. Spring AOP不起作用原因
  20. XXE漏洞

热门文章

  1. Object[] cannot be converted to String[]
  2. C# 使用 log4net 日志组件
  3. Spring-构造注入&amp;注解注入&amp;代理模式&amp;AOP
  4. 学习一下 SpringCloud (三)-- 服务调用、负载均衡 Ribbon、OpenFeign
  5. Jmeter(三十四) - 从入门到精通进阶篇 - 参数化(详解教程)
  6. ElasticSearch教程——filter与query对比(转学习使用)
  7. JavaScript入门-学习笔记(二)
  8. log4net配置及使用
  9. 分装button组件引发的内存泄漏问题
  10. 机器学习算法&#183;KNN