Redis-based distributed lock prevents high concurrent repeated requests

demand:

Let us first give a list of examples of system verification: (A channel system, business B system, external vendor C system)
(1) The B business system calls the A channel system to verify whether the incoming mobile phone, ID card, and name are consistent.
(2) The A channel system calls the external vendor C system.
(3) The A channel system returns the result to the B business system.

Of these 3 processes, (2) process, calling external vendors requires billing.
When the concurrency of the B business system is very high, there are 100 identical three-element verifications. Since the three elements are the same, the A channel only needs to call the manufacturer once to know the result. In order to prevent other requests from calling the external system at the same time when a request has not been responded to, this time requires locking processing

Features of distributed locks

Atomicity: only one thread of a machine
can get the lock at the same time; reentrancy: the same object (such as a thread, class) can repeatedly and recursively call the lock without deadlock;
blockable: when the lock is not acquired Previously, you could only block and wait until the lock was acquired;
high availability: even if a program failure or machine damage occurs, the lock can still be acquired and released;
high performance : the operation of acquiring and releasing the lock consumes little.

To achieve: lock, reduce lock, lock timeout
can be achieved by: database mc redis system file zookeeper

I am now a channel system. When 100 identical business requests are passed over, my first request is to lock first, then request an external vendor system, wait for the response, insert another key, and then delete the lock.
Other requests go to get the lock first, if there is already a lock, it will find and wait, if the lock is no longer there, go directly to the query result.
If the first request fails and the result is not inserted in place, continue to acquire the lock and then query the external system.

Acquire the lock:
$ redis-> set ('lock: mobile phone number & ID card & name', 1, ['nx', 'ex' => 10]);
release the lock:
just delete the key
lock timeout:
lock key has timeout

The new version of the redis set command can implement distributed locks. It can also implement both set and timeout if it does not exist.

<?php
$redis=new Redis();
$redis->connect("127.0.0.1",6379);
//高并发时防止重复请求

//渠道系统传递过来的key
$lockKey='lock:18806767777&37781991111629092&taoshihan';
$resultKey='res:18806767777&37781991111629092&taoshihan';

//如果已经查询过值,可以直接返回
$info=$redis->get($resultKey);
if($info){
exit($info);
}

//如果没有值的,获取锁
$lock=$redis->set($lockKey, 1, ['nx', 'ex'=>10]);
if($lock){
//请求外部系统获取结果,比如响应结果比较慢
sleep(8);
$info='{"name":"taoshihan"}';
$ret=$redis->set($resultKey,$info);
if($ret){
//删除锁
$redis->del($lockKey);
exit($info);
}
}
echo "请稍后重试!";

Guess you like

Origin www.cnblogs.com/myJuly/p/12684028.html