当前位置:Gxlcms > 数据库问题 > 使用Mysql和Redis设计抢购逻辑

使用Mysql和Redis设计抢购逻辑

时间:2021-07-01 10:21:17 帮助过:4人阅读

TABLE `la_store` ( `id` int(11) NOT NULL, `val` int(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

假设库存有100000件(val=100000)

php逻辑代码

  1. <?<span style="color: #000000">php
  2. </span><span style="color: #800080">$stime</span>=<span style="color: #008080">microtime</span>(<span style="color: #0000ff">true</span><span style="color: #000000">);
  3. </span><span style="color: #800080">$count</span>=100000<span style="color: #000000">;//测试次数
  4. </span><span style="color: #0000ff">while</span>(<span style="color: #800080">$count</span>>0<span style="color: #000000">){
  5. </span><span style="color: #800080">$count</span>-=1<span style="color: #000000">;
  6. </span><span style="color: #800080">$con</span> = <span style="color: #008080">mysql_connect</span>("localhost","user","pwd"<span style="color: #000000">);
  7. </span><span style="color: #0000ff">if</span> (!<span style="color: #800080">$con</span><span style="color: #000000">)
  8. {
  9. </span><span style="color: #0000ff">die</span>(‘Could not connect: ‘ . <span style="color: #008080">mysql_error</span><span style="color: #000000">());
  10. }
  11. </span><span style="color: #008080">mysql_select_db</span>("database_name", <span style="color: #800080">$con</span><span style="color: #000000">);
  12. </span><span style="color: #008080">mysql_query</span>(‘begin‘<span style="color: #000000">);
  13. </span><span style="color: #800080">$record</span>=<span style="color: #008080">mysql_query</span>("select * from la_store where id = 1 for update");<span style="color: #008000">//</span><span style="color: #008000">获取独占锁</span>
  14. <span style="color: #800080">$record</span>=<span style="color: #008080">mysql_fetch_array</span>(<span style="color: #800080">$record</span><span style="color: #000000">);
  15. </span><span style="color: #0000ff">if</span>(<span style="color: #800080">$record</span>[‘val‘]>0){<span style="color: #008000">//</span><span style="color: #008000">判断是否还有库存
  16. //有库存的逻辑</span>
  17. <span style="color: #800080">$res</span>=<span style="color: #008080">mysql_query</span>("UPDATE la_test SET val = val-1 WHERE id=1 ");<span style="color: #008000">//</span><span style="color: #008000">更新库存</span>
  18. <span style="color: #000000">}else{<br>//没库存的逻辑<br>}
  19. </span><span style="color: #008080">mysql_query</span>("commit"<span style="color: #000000">);
  20. </span><span style="color: #008080">mysql_close</span>(<span style="color: #800080">$con</span><span style="color: #000000">);
  21. }
  22. </span><span style="color: #800080">$etime</span>=<span style="color: #008080">microtime</span>(<span style="color: #0000ff">true</span>);<span style="color: #008000">//</span><span style="color: #008000">获取程序执行结束的时间</span>
  23. <span style="color: #800080">$total</span>=<span style="color: #800080">$etime</span>-<span style="color: #800080">$stime</span><span style="color: #000000">;
  24. </span><span style="color: #0000ff">echo</span> <span style="color: #800080">$total</span>;

方案二.使用Redis开启事务

假设库存有100000件(set store 100000)

  1. <?<span style="color: #000000">php
  2. </span><span style="color: #800080">$stime</span>=<span style="color: #008080">microtime</span>(<span style="color: #0000ff">true</span><span style="color: #000000">);//开始时间
  3. </span><span style="color: #800080">$count</span>=100000<span style="color: #000000">;//测试次数
  4. </span><span style="color: #0000ff">while</span>(<span style="color: #800080">$count</span>>0<span style="color: #000000">){
  5. </span><span style="color: #800080">$count</span>-=1<span style="color: #000000">;
  6. </span><span style="color: #800080">$redis</span> = <span style="color: #0000ff">new</span><span style="color: #000000"> Redis();
  7. </span><span style="color: #800080">$redis</span>->connect(‘127.0.0.1‘, 6379<span style="color: #000000">);
  8. </span><span style="color: #800080">$res</span>=<span style="color: #800080">$redis</span>->multi()->decr(‘store‘)->get(‘store‘)-><span style="color: #008080">exec</span><span style="color: #000000">();
  9. </span><span style="color: #0000ff">if</span>(<span style="color: #800080">$res</span>[1]>0<span style="color: #000000">){
  10. </span><span style="color: #008000">//有库存</span><span style="color: #008000">逻辑</span>
  11. }<span style="color: #0000ff">else</span><span style="color: #000000">{
  12. </span><span style="color: #008000">//</span><span style="color: #008000">没有库存逻辑</span>
  13. <span style="color: #000000">}
  14. }
  15. </span><span style="color: #800080">$etime</span>=<span style="color: #008080">microtime</span>(<span style="color: #0000ff">true</span>);<span style="color: #008000">//</span><span style="color: #008000">获取程序执行结束的时间</span>
  16. <span style="color: #008080">print_r</span>(<span style="color: #800080">$res</span><span style="color: #000000">);
  17. </span><span style="color: #800080">$total</span>=<span style="color: #800080">$etime</span>-<span style="color: #800080">$stime</span><span style="color: #000000">;
  18. </span><span style="color: #0000ff">echo</span> <span style="color: #800080">$total</span>;

测试结果:

分别执行,经过100000次循环后,Redis用时22秒,Mysql用时50秒;

使用Redis更快,但Redis的事务不能回滚,如果业务逻辑出错时允许不回滚,并且回滚的概率很小,建议使用Redis.如果逻辑出错时必须回滚,还是用Mysql更稳妥.

使用Mysql和Redis设计抢购逻辑

标签:ble   record   charset   err   while   mys   时间   开始时间   div   

人气教程排行