Verwenden Sie dazu die Redis-verknüpfte Liste, da die Pop-Operation atomar ist. Auch wenn viele Benutzer gleichzeitig ankommen, werden sie nacheinander ausgeführt, was empfohlen wird.
Der erste Schritt besteht darin, den Produktbestand in die Warteschlange zu stellen
/** * 添加商品数量到商品队列 * @param int $couponId 优惠券ID */ function addCoupons($couponId) { //1.初始化Redis连接 $redis = new Redis(); if (!$redis->connect('127.0.0.1', 6379)) { trigger_error('Redis连接出错!!!', E_USER_ERROR); } else { echo '连接正常
'; } //根据优惠券ID从数据库中查询该优惠券的库存量 //$sql = "select id, stock from coupon where id = {$couponId}"; $stock = 10; //假设10就是我们从数据库中查询出的该优惠券在数据库中的库存量 //我们现在将这10个库存放入到以该商品ID为key的redis链表中,有几件库存,就存入多少次1,链表长度代表商品库存数 for($i = 0; $i < $stock; $i++) { $redis->lPush("secKill:".$couponId.":stock", 1); } $redis->close(); } $couponId = 11211; addCoupons($couponId);
Wir rufen diese Methode auf und überprüfen dann Redis. 10 Elemente wurden zur verknüpften Liste hinzugefügt Starten Sie den Ansturm und legen Sie den Cache-Zeitraum fest
Dieser Schritt richtet sich nach Ihrem eigenen Unternehmen. Wenn das Unternehmen vorschreibt, dass der Coupon 2 Minuten lang für Benutzer freigegeben wird, legen Sie einen Gültigkeitszeitraum für die verknüpfte Liste fest Die-Methode gilt auch dann, wenn sie nicht innerhalb der Gültigkeitsdauer abgerufen wird. Der Bestand darf nicht von Benutzern abgerufen werden (da das Unternehmen unseres Unternehmens keine Gültigkeitsdauer für die Abholung von Gutscheinen festlegt, ist dies nicht erforderlich Führen Sie diesen Schritt aus)
//设置链表有效期是两分钟 $redis->expire('key', 120);
Im dritten Schritt führt der Client den Instant-Snap-up-Vorgang aus
/** * 抢优惠券(秒杀) * @param int $couponId 商品ID * @param int $uid 用户ID * @return bool */ function secKill($couponId, $uid) { //1.初始化Redis连接 $redis = new Redis(); if (!$redis->connect('127.0.0.1', 6379)) { trigger_error('Redis连接出错!!!', E_USER_ERROR); } else { echo '连接正常
'; } //将已经成功抢购的用户添加到该以该商品ID为key的集合(set)中 //如果用户已经在集合中,说明用户已经成功秒杀过一次了,不允许再次参与秒杀 if ($redis->sIsMember('secKill:'.$couponId.':uid', $uid)) { echo '秒杀失败'; return false; } //秒杀商品的库存key $key = 'secKill:'.$couponId.':stock'; //从以该优惠券ID为key的链表中弹出一个值,如果有值,证明优惠券还有库存 $isSockNotEmpty = $redis->lPop($key); //判断库存,如果库存大于0,则减库存,将该成功秒杀用户加入哈希表,如果小于等于0,秒杀结束 if ($isSockNotEmpty != 1) { echo '秒杀已结束'; return false; } //抢券成功,将优惠券ID和UID放入到队列中,由一个单独的进程队列来消费队列里的数据,向用户推送抢到的优惠券 $redis->lPush('couponOrder', $couponId.'+'.$uid); //将成功抢券的用户记录到集合中,防止被已抢过的用户再次秒杀 $redis->sAdd('secKill:'.$couponId.':uid', $uid); $redis->close(); return true; } $couponId = 11211; $uid = mt_rand(1, 100); secKill($couponId, $uid);
Im vierten Schritt geben Flash-Sale-Benutzer persistente Daten in die Datenbank ein Nach einem erfolgreichen Kauf können wir die Informationen im dritten Schritt direkt in die Datenbank schreiben. Für diejenigen mit einer relativ großen Parallelität können sie zur Verwendung in die RabbitMQ-Nachrichtenwarteschlange gestellt werden (empfohlen). Der Grund für die Verwendung der RabbitMQ-Warteschlange Redis besteht darin, dass RabbitMQ sicherstellen kann, dass Nachrichten zu 100 % verbraucht werden, während Redis relativ weniger stabil und zuverlässig ist Dann verwenden wir den Redis Desktop Manager, um die Redis-Ergebnisse anzuzeigenexpire()
Gleichzeitig werden auch die UID-Informationen von 10 Benutzern in der Benutzercoupon-Sammlung gespeichert.
Das obige ist der detaillierte Inhalt vonSo verwenden Sie die verknüpfte Redis-Liste, um das Problem überverkaufter Produkte mit hoher Parallelität zu lösen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!