Spiderwebには、多くのショッピングカード、映画クーポン、およびバウチャーがあります。
たとえば、舞台裏の需要では、現時点で100,000枚のカード番号の新しいバッチを生成する必要があります。WeChatチャネル用に30,000、メインサイト、アプリ用に50,000、外部チャネル用に20,000です。
では、カード番号を繰り返さずにすばやく生成するにはどうすればよいでしょうか。
ロジックは非常に単純です。何らかの方法でランダムなカード番号を生成し、データベースにアクセスして重みを並べ替え、100,000まで繰り返さずに挿入します。
1.カード番号の生成方法は?
さまざまな業種を区別できます。伝票はDYで始まり、引き換えチケットはDHで始まります。これは、繰り返しの際のクエリを高速化するためです。引き続きディメンションを追加できます。
2.速度を生成して確保する方法は?
当初は、クエリの繰り返しを避けるためにカード番号データを生成する方法しか考えていなかったため、カードの長さが短くなる可能性が低く、エクスペリエンスも良くありません。
後で、同僚がプロシージャを格納するように私に思い出させたとき、ストアドプロシージャを記述します。
ストレージプロセスの結果も比較的遅く、1000個で約33秒です。それから私はその同僚にバッチで尋ねました。私はmysqlバッチについて考えます
set autocommit=0;
CREATE TABLE `biz_card` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`cardno` varchar(50) DEFAULT NULL,
`status` tinyint(4) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `ix_cardno` (`cardno`)
) ENGINE=InnoDB AUTO_INCREMENT=7303 DEFAULT CHARSET=utf8;
DROP PROCEDURE IF EXISTS `genCardNo`;
CREATE PROCEDURE genCardNo(IN num int)
begin
-- 产生一个随机7位数
DECLARE newCard int;
set autocommit=0;
while num>0 do
SET newCard=FLOOR(10000000+ (RAND() * 89999999));
select @repCount:=count(id) from biz_card where cardno=CONCAT('DY',newCard);
-- 重复判断
if @repCount>0 THEN
SELECT concat('the value is repeat:', 'DY',newCard);
else
insert biz_card(cardno,status)values(CONCAT('DY',newCard),0);
set num = num - 1;
if num%5000=0 then
SELECT concat('begin commit,num:',num);
commit;
end if;
end if;
end WHILE;
commit;
end;
[SQL] call genCardNo(1000);
受影响的行: 1
时间: 0.3s
[SQL] call genCardNo(100000);
影響を受ける行:0
時間:15.350秒
これは問題ないようです。データ量が多い場合、次のアイデアは、メッセージキューを介してデータを別のマシンに配布して生成し、redisを使用して重みを保存および処理することです。