如何在发放优惠码时保证同一个码不会被重复发出多次?

2015-03-16 12:15:05 +08:00
 kran

表结构如下:

`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '编号',
`coupon` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '优惠券码',
`type` tinyint(1) unsigned NOT NULL COMMENT '类型',
`is_use` enum('N','Y') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'N' COMMENT '是否使用',
`use_date` int(10) unsigned NOT NULL COMMENT '使用时间',
`is_del` enum('N','Y') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'N' COMMENT '是否删除',
`creation_date` int(10) unsigned NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `type` (`type`,`is_use`,`is_del`)

现在使用这样的查询,会锁表:

begin;
select * from coupon_list where is_use='N' and type=5 and is_del='N' limit 1 for update;

如何才能触发行锁而不是表锁?

6333 次点击
所在节点    MySQL
37 条回复
kran
2015-03-16 14:44:45 +08:00
@laoyur
也就是同步的方法吗? 如果是这样的话,直接表锁也和它差不多了吧?
kran
2015-03-16 14:49:55 +08:00
@happywowwow 文章里说的是,使用相同索引那么就会对索引加锁,跟锁表差不多。

@zhicheng 对哦!进程数是有个大概范围的。我真是笨死了 T_T
看来这个场景下之需要所表就ok的。
能问一下100k以上需要那些处理吗?
kran
2015-03-16 14:51:05 +08:00
@zhicheng 啊。按终端分就是处理方法吗?
zhicheng
2015-03-16 14:53:55 +08:00
一个数据库肯定顶不住,在创建优惠码之后可以分布到多个数据库里,同时读写,等一批码发完最后同步一下。这种方式可以任凭你分布到多少服务器上都不会互相影响。
kran
2015-03-16 15:00:01 +08:00
@zhicheng 非常好!感谢ing!
zhicheng
2015-03-16 15:02:37 +08:00
恭喜你掌握了每秒顶住10亿红包系统的秘密。。。
kran
2015-03-16 15:13:38 +08:00
@zhicheng 别吓唬我,我最怕知道秘密了~哈哈
ayv
2015-03-16 15:16:27 +08:00
把优惠码放到一个持久化的队列 例如redis的list
happywowwow
2015-03-16 15:28:55 +08:00
”InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!“
lujjjh
2015-03-16 15:37:35 +08:00
如果一定要用 MySQL,为什么要设计成记录“优惠码是否使用”而不是记录“优惠码拥有者”呢?
先 SELECT 再 UPDATE 原子性难以得到保证的话,最简单的方案就是先 UPDATE 再 SELECT 嘛。
julyclyde
2015-03-16 21:13:50 +08:00
@abelyao 临时生成会比较慢,再加上判断重复、判断重复、判断重复、判断重复的耗时就可能超时了
@c742435
abelyao
2015-03-16 21:28:23 +08:00
@julyclyde 可没说临时生成就必须做重复判断哦,可以把 unique id 视作优惠码多一部分,算法有很多种,就看你怎么设计了。当然楼主说优惠码是已经有客户那边生成了,就不再讨论这个方案了。
lujiajing1126
2015-03-16 23:04:21 +08:00
@lujjjh select的时候加悲观锁
或者用version_code做乐观锁
lujiajing1126
2015-03-16 23:05:22 +08:00
话说为啥不试试redis的list。。。
很多抢票都是这么干的
donglingyongadls
2015-03-17 10:01:58 +08:00
借鉴bloom filter?没试过,仅供参考
ly827
2015-03-17 11:55:56 +08:00
貌似是新浪游戏的面试题啊~~可以尝试事务处理+for update~保证唯一 看情况决定用不用存储过程
li24361
2015-03-24 23:23:44 +08:00
@zhicheng 腾讯就是利用狂加数据库来顶住的压力,我觉得不只是堆数据库这么简单吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/177228

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX