1.并发访问限制问题
对于一些需要限制同一个用户并发访问的场景,如果用户并发请求多次,而服务器处理没有加锁限制,用户则可以多次请求成功。
例如换领优惠券,如果用户同一时间并发提交换领码,在没有加锁限制的情况下,用户则可以使用同一个换领码同时兑换到多张优惠券。
伪代码如下:
<code class="hljs scss has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">if <span class="hljs-function" style="box-sizing: border-box;">A(可以换领)</span>
<span class="hljs-function" style="box-sizing: border-box;">B(执行换领)</span>
<span class="hljs-function" style="box-sizing: border-box;">C(更新为已换领)</span>
<span class="hljs-function" style="box-sizing: border-box;">D(结束)</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
如果用户并发提交换领码,都能通过可以换领(A)的判断,因为必须有一个执行换领(B)后,才会更新为已换领(C)。因此如果用户在有一个更新为已换领之前,有多少次请求,这些请求都可以执行成功。
2.并发访问限制方法
使用文件锁可以实现并发访问限制,但对于分布式架构的环境,使用文件锁不能保证多台服务器的并发访问限制。
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
本文将使用其setnx方法实现分布式锁功能。setnx即Set it N**ot eX**ists。
当键值不存在时,插入成功(获取锁成功),如果键值已经存在,则插入失败(获取锁失败)
RedisLock.class.php
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><?php
<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
* Redis锁操作类
* Date: 2016-06-30
* Author: fdipzone
* Ver: 1.0
*
* Func:
* public lock 获取锁
* public unlock 释放锁
* private connect 连接
*/</span>
class RedisLock { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// class start</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> $_config;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> $_redis;
<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
* 初始化
*<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> Array $config redis连接设定
*/</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> function <span class="hljs-title" style="box-sizing: border-box;">__construct</span>($config=array()){
$<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_config = $config;
$<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_redis = $<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->connect();
}
<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
* 获取锁
*<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> String $key 锁标识
*<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> Int $expire 锁过期时间
*<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @return</span> Boolean
*/</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> function <span class="hljs-title" style="box-sizing: border-box;">lock</span>($key, $expire=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>){
$is_lock = $<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_redis->setnx($key, time()+$expire);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 不能获取锁</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(!$is_lock){
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 判断锁是否过期</span>
$lock_time = $<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_redis->get($key);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 锁已过期,删除锁,重新获取</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(time()>$lock_time){
$<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->unlock($key);
$is_lock = $<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_redis->setnx($key, time()+$expire);
}
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> $is_lock? <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">true</span> : <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
}
<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
* 释放锁
*<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> String $key 锁标识
*<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @return</span> Boolean
*/</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> function <span class="hljs-title" style="box-sizing: border-box;">unlock</span>($key){
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> $<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_redis->del($key);
}
<span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
* 创建redis连接
*<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @return</span> Link
*/</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> function <span class="hljs-title" style="box-sizing: border-box;">connect</span>(){
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span>{
$redis = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Redis();
$redis->connect($<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_config[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'host'</span>],$<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_config[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'port'</span>],$<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_config[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'timeout'</span>],$<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_config[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'reserved'</span>],$<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_config[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'retry_interval'</span>]);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(empty($<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_config[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'auth'</span>])){
$redis->auth($<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_config[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'auth'</span>]);
}
$redis->select($<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>->_config[<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'index'</span>]);
}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span>(RedisException $e){
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Exception($e->getMessage());
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> $redis;
}
} <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// class end</span>
?></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li></ul>
demo.php
<code class="hljs php has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"><?php</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">require</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'RedisLock.class.php'</span>;
<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$config</span> = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">array</span>(
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'host'</span> => <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'localhost'</span>,
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'port'</span> => <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6379</span>,
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'index'</span> => <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>,
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'auth'</span> => <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">''</span>,
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'timeout'</span> => <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'reserved'</span> => <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">NULL</span>,
<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'retry_interval'</span> => <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">100</span>,
);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 创建redislock对象</span>
<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$oRedisLock</span> = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> RedisLock(<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$config</span>);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 定义锁标识</span>
<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$key</span> = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'mylock'</span>;
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 获取锁</span>
<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$is_lock</span> = <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$oRedisLock</span>->lock(<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$key</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$is_lock</span>){
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">echo</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'get lock success<br>'</span>;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">echo</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'do sth..<br>'</span>;
sleep(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">echo</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'success<br>'</span>;
<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$oRedisLock</span>->unlock(<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">$key</span>);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 获取锁失败</span>
}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">echo</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'request too frequently<br>'</span>;
}
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">?></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li></ul>
测试方法:
打开两个不同的浏览器,同时在A,B中访问demo.php
如果先访问的会获取到锁
输出
get lock success
do sth..
success
另一个获取锁失败则会输出request too frequently
保证同一时间只有一个访问有效,有效限制并发访问。
为了避免系统突然出错导致死锁,所以在获取锁的时候增加一个过期时间,如果已超过过期时间,即使是锁定状态都会释放锁,避免死锁导致的问题。
源码下载地址:点击查看
本文探讨了在并发场景下如何限制用户的重复请求,尤其是在换领优惠券等场景中。利用Redis的setnx方法实现分布式锁功能,确保同一时刻只有一个请求有效。
342

被折叠的 条评论
为什么被折叠?



