分布式锁与信号量

**分布式锁,是指在分布式的部署环境下,通过锁机制来让多客户端互斥的对共享资源进行访问。
信号量的本质也是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源来实现进程间通信,从而负责数据操作的互斥与同步。
本实训项目的主要内容是使用 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 *********#

!!!!感谢大家的支持!!!!

猜你喜欢

转载自blog.csdn.net/weixin_44196785/article/details/109964531
今日推荐