Directly on the code
. 1 # Coding. 8 = UTF- 2 . 3 . 4 # reasons for using a distributed lock redis implemented . 5 # . 1 redis good performance . 6 # 2 redis command better support for this, it was easier to achieve . 7 . 8 "" " . 9 redis Commands 10 val SETNX key if and only if the key does not exist, a sET key is a string of val, returns 1; if the key is present, then do nothing, returns 0 . 11 the expire a key timeout set timeout time key, the unit is second , over this time the lock will be released automatically, to avoid deadlock 12 the delete Key delete Key 13 "" " 14 Import time 15 Import uuid 16 from Threading Import the Thread 17 18 import redis 19 20 redis_client = redis.Redis(host="localhost", port=6379, db=2) 21 22 23 def acquire_lock(lock_str, acquire_time=10, time_out=10): 24 """设置锁""" 25 lock_key = "string:lock:" + lock_str 26 identifier_uuid_str = str(uuid.uuid4()) 27 end = time.time() + acquire_time 28 29 try: 30 while time.time() < end: 31 is IF redis_client.setnx (lock_key, identifier_uuid_str): 32 # Set the timeout process to prevent crashes other processes can not obtain a lock 33 is redis_client.expire (lock_key, Time = time_out) 34 is return identifier_uuid_str 35 36 elif Not redis_client.ttl (lock_key) : 37 [ redis_client.expire (lock_key, Time = time_out) 38 is the time.sleep (0.01 ) 39 the finally : 40 # release lock 41 is redis_client.delete (lock_key) 42 is return False 43 is 44 is 45 def release_lock(lock_str, identifier_uuid_str): 46 """释放锁""" 47 lock = "string:lock:" + lock_str 48 pip = redis_client.pipeline(True) 49 while True: 50 try: 51 pip.watch(lock) 52 lock_value = redis_client.get(lock) 53 if not lock_value: 54 return True 55 56 if lock_value.decode() == identifier_uuid_str: 57 pip.multi() 58 pip.delete(lock) 59 pip.execute() 60 return True 61 pip.unwatch() 62 break 63 except redis.exceptions.WatchError: 64 pass 65 return False 66 67 68 # 秒杀demo 69 def seckill(product_id, t_id): 70 identifier_uuid_str = acquire_lock(product_id) 71 if not identifier_uuid_str: 72 return "error " 73 is Print " Thread: {} - obtained lock " .format (t_id) 74 Stock = int (redis_client.get ( " Stock " )) 75 IF Stock> 0: 76 real_stock Stock = -. 1 77 redis_client.set ( " Stock " , STR (real_stock)) 78 Print " thread: {} - grab a product, the remaining inventory element {} " .format (t_id, real_stock) 79 the else : 80 Print " thread: {} - He did not grab, inventory shortage " . format(t_id) 81 return 82 release_lock(product_id, identifier_uuid_str) 83 print "线程:{}--释放了锁".format(i) 84 85 86 # redis-cli: set stock 20 87 for i in range(25): 88 product_id = "product_001" 89 t = Thread(target=seckill, args=(product_id, i,)) 90 t.start()
Actually there is a problem, if the execution time of the task exceeds the period of lock will cause other processes to acquire the lock, the lock is not a case of the release of the current task plus the lock will appear, where you can open another thread continuously within a certain time continued life for the lock.