redis分布式锁

最近看了一些redis方面的书籍,对分布式锁重点看了一下,觉得想写出一把优秀的分布式锁真的非常难,下面我做一个秒杀商品的分布式锁。

使用flask简单模拟一个秒杀场景。

首先最简单的分布式锁一般是使用一个 setnx即可,但是如果在秒杀业务的过程中出现了代码报错怎么办?ok,我们想到了用try…finally…,没问题,但是如果是出现了断电呢?那么我们的分布式锁就永远得不到释放了,所以在写分布式锁时,要设置一个超时时间。还有就是为什么要用一个uuid作为分布式锁的value呢?是不是用一个随便什么数都能作为锁的value?
其实不是的,例如A进程,当执行到try 中的代码时,因为一些因素,比如进程调度等等因素,他设置的分布式锁已经超时被redis删除掉了,那么此时进程B就得到了这把锁,然后B去执行业务,但此时是不是可能出现A进程执行完毕,A执行了释放分布式锁的代码?那么如果不加以控制,就会出现A释放了B的分布式锁。此时如果并发极高,会立刻有新的进程得到了这把锁,从而进入了业务代码,造成两个进程同时进入业务代码的情况,这种情况是不能容忍的。
所以呢,我们要生成一个唯一的uuid来标示这把分布式锁是我设置的,只能我去解除,别人不可以。

当然,这把分布式锁还不完善,在大并发下还有很多的bug,

import redis,uuid
from flask import Flask, request


pool = redis.ConnectionPool(host='127.0.0.1',port=6379,password='',decode_responses=True,db=5)
r = redis.Redis(connection_pool=pool)

app = Flask(__name__)

@app.route('/')
def hello():

    clientid = str(uuid.uuid4())
    if r.setnx('mutex',clientid):
        # 其实这一步和if语句应该合并成一个原子操作执行,
        但是现在还没有在pyredis中找到支持的方法,java语言的jedis貌似是支持的
        r.expire('mutex',10)
    else:
        return '在线人数较多,请稍后再试。'

    try:
        g_num = int(r.get('goods'))
        if g_num > 0:
            r.decr('goods')
            status = True
        else:
            status = False
    finally:
        if r.get('mutex') == clientid:  # 释放锁
            r.delete('mutex')


    return '抢货成功~!' if status else '货已售完~0.0'


if __name__ == '__main__':
    app.run()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值