**分布式锁,是指在分布式的部署环境下,通过锁机制来让多客户端互斥的对共享资源进行访问。
信号量的本质也是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源来实现进程间通信,从而负责数据操作的互斥与同步。
本实训项目的主要内容是使用 Redis 构建锁和信号量,进一步提高 Redis 性能。我们将通过构建简易锁,超时限制锁,计数信号量和公平信号量来掌握分布式锁与信号量的相关知识。
**
简易锁
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import uuid
import time
import redis
conn = redis.Redis()
# 获得锁
def acquire_lock(lockname, acquire_timeout=5):
# 请在下面完成要求的功能
#********* Begin *********#
identifier = str(uuid.uuid4())
end = time.time() + acquire_timeout
while time.time() < end:
if conn.setnx('lock:' + lockname, identifier):
return identifier
time.sleep(0.001)
return False
#********* End *********#
# 释放锁
def release_lock(lockname, identifier):
# 请在下面完成要求的功能
#********* Begin *********#
pipe = conn.pipeline()
lockname = 'lock:' + lockname
while True:
try:
pipe.watch(lockname)
if pipe.get(lockname) == identifier:
pipe.delete(lockname)
return True
pipe.unwatch()
break
except redis.exceptions.WatchError:
pass
return False
#********* End *********#
超时限制锁
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import uuid
import time
import redis
conn = redis.Redis()
# 获得超时限制锁
def acquire_lock_with_timeout(lockname, acquire_timeout=10, lock_timeout=10):
# 请在下面完成要求的功能
#********* Begin *********#
identifier = str(uuid.uuid4())
lockname = 'lock:' + lockname
end = time.time() + acquire_timeout
while time.time() < end:
if conn.setnx(lockname, identifier):
conn.expire(lockname, lock_timeout)
return identifier
elif conn.ttl(lockname) < 0:
conn.expire(lockname, lock_timeout)
time.sleep(0.001)
return False
#********* End *********#
计数信号量
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import uuid
import time
import redis
conn = redis.Redis()
# 获得计数信号量
def acquire_semaphore(semname, limit=5, timeout=10):
# 请在下面完成要求的功能
#********* Begin *********#
identifier = str(uuid.uuid4())
now = time.time()
pipeline = conn.pipeline()
pipeline.zremrangebyscore(semname, '-inf', now - timeout)
pipeline.zadd(semname, identifier, now)
pipeline.zrank(semname, identifier)
if pipeline.execute()[-1] < limit:
return identifier
conn.zrem(semname, identifier)
return None
#********* End *********#
# 释放计数信号量
def release_semaphore(semname, identifier):
# 请在下面完成要求的功能
#********* Begin *********#
return conn.zrem(semname, identifier)
#********* End *********#
公平信号量
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import uuid
import time
import redis
conn = redis.Redis()
# 获得公平信号量
def acquire_fair_semaphore(semname, limit=5, timeout=10):
# 请在下面完成要求的功能
#********* Begin *********#
identifier = str(uuid.uuid4())
czset = semname + ':owner'
ctr = semname + ':counter'
now = time.time()
pipeline = conn.pipeline(True)
pipeline.zremrangebyscore(semname, '-inf', now - timeout)
pipeline.zinterstore(czset, {
czset: 1, semname: 0})
pipeline.incr(ctr)
counter = pipeline.execute()[-1]
pipeline.zadd(semname, identifier, now)
pipeline.zadd(czset, identifier, counter)
pipeline.zrank(czset, identifier)
if pipeline.execute()[-1] < limit:
return identifier
pipeline.zrem(semname, identifier)
pipeline.zrem(czset, identifier)
pipeline.execute()
return None
#********* End *********#
# 释放公平信号量
def release_fair_semaphore(semname, identifier):
# 请在下面完成要求的功能
#********* Begin *********#
pipeline = conn.pipeline()
pipeline.zrem(semname, identifier)
pipeline.zrem(semname + ':owner', identifier)
return pipeline.execute()[0]
#********* End *********#
!!!!感谢大家的支持!!!!