小而美的邀请码设计实现方案

互联网公司推出新产品的时候,经常使用邀请码作为一种运营手段,在一定的时间内,只有具有邀请资格的用户,才能参与到早期产品的体验中去。
这么做,一方面为了体现产品体验的稀缺性,鼓励用户抢购,造成供不应求的舆论影响。这点小米做的尤为突出,效果也是相当不错的。另一方面,先让一部分比较有热情的早期种子用户进来,也能够充分的对产品的易用性和体验流程进行早期的验证,方便手机用户的反馈之后迭代修改。·

我们首先来看看根据需求邀请码服务需要提供出哪些接口:

  • 单个或批量的生成邀请码,要求六位,数字与字符的混合,供运营和用户使用;
  • 给用户激活邀请码;
  • 校验用户是否已经激活邀请码;
  • 批量给已注册用户绑定几个可用的邀请码,方便二次传播;
  • 查询用户名下已经绑定的邀请码和其被激活的情况,验证二次传播的效果

根据需求,现有的技术实现方案有很多,核心来讲的话主要有两点:

  • 邀请码生成算法与唯一性保证
  • 邀请码高效查询与激活

另外还有一些其他的点,会在文中慢慢道来。

邀请码的生成方式

产品的要求是六位,同时字母和数字混合的方式,一共会发放10000个左右。一开始的思路是使用纯算法的方式实现,通过生成唯一的ID,增加一些共性的信息,再根据信息摘要的方式,映射成字母与数字的混合,不过试了一下,算法实现的成本比较高,而且还有借助额外的唯一ID生成的工具,所以有些得不偿失。
另外由于不能是纯数字,所以十六进制映射的方案也无法进行。而且也不能是一长串的字符,这样md5的方案也无法实施了。

所以在这样的前提之下,决定使用简单算法+redis来做整个方案。
首先是邀请码的生成,由于生成的过程一般是后台或者手动触发,所以对性能的要求并不太高,也就是说,允许一定程度的碰撞。所谓的碰撞,就是算法算出来的邀请码,和已经生成的邀请码重复了。所以我们来算一下概率:
一共是六位的邀请码,每一位的组成是大小写字母+阿拉伯数字,也就是26+26+10=62种可能性。所以六位也就是一共能够产生出62^6=56,800,235,584即560亿个邀请码,产品的要求是一共放出去一万个,所以即使现在已经有一万个邀请码被生成了,那么生成一个邀请码和现有邀请码重复的概率只是10000/560亿, 非常低的概率,如果真的中了大奖,那么就进行二次生成,再次碰撞的概率,恐怕就更低了。

同时为了保证邀请码看起来更真实,再增加一个连续两位不能重复的验证,同时每次生成结束之后,使用redis验证是否唯一,即可实现整个邀请码的生成过程。

数据结构的设计

上文说到为了保证邀请码的唯一性,必须使用redis,redis中的集合数据结构就提供了很好支持。每次生成完成后,只需要调用isMember validatorSet方法,即可根据返回判断是否已经生成了邀请码。

同时使用集合存储邀请码,也能够满足统计的需求,只需要定时执行smembers validatorSet,即可统计出所有生成出来的邀请码。

另外,由于存在用户激活邀请码,和查询是否已经激活邀请码的寻求,所以必须对此设计专门的数据结构。查询需求是高频需求,在用户量比较大的情况下,会有比较大的访问压力。同时为了扩展可能存储的用户其他信息,所以使用散列的数据类型进行存储。
每次查询用户是否已经激活,只需要执行hget user:$guid validator 即可获取其中的邀请码信息,从而判断出用户是否已经激活。

而用户激活的过程,涉及的数据结构稍多,每次激活的过程,都需要分成几步:
第一步是查询这个邀请码是否是合法有效的邀请码,需要使用ismember validatorSet进行判断;
如果合法有效,第二步是设置用户的激活状态,即上文中所用到的这个散列hset user:$guid validator {$validator};
第三步则是设置邀请码本身的状态,即这个邀请码被哪个用户用了,方便之后查询 set validator:{$validator}:status {'userName':ted,'avatar':'http://test.com'}

由于第二步和第三步必须保证数据的幂等性,因此需要使用redis的事务来进行执行,保证两者能够同时成功的被执行:

$redis->Multi()
->set validator:{$validator}:status {'userName':ted,'avatar':'http://test.com'}
->hset user:$guid validator {$validator}
->exec()

但是除了使用事务,还需要规避的就是两个用户同时取到了同一个邀请码,在同一时间进行了激活的操作,在高并发的情况下,会有原子性的问题。所以必须引入redis中的watch命令,监控邀请码的status这个key,保证一旦它被变更了,那么当前的事务就不再执行,从而避免给用户带来错误的反馈:
redis->watch validator:{$validator}:status

由此,就完成了用户邀请码的激活过程。

除此之外,还有个小功能,那就是给一批种子用户绑定几个邀请码,并在邀请码被激活之后,展示出相应的状态。刚刚说到了用户为维度的那个哈希表结构,是时候给它再加一个field了,这个field就叫boundValidators,专门用来存储用户名下被绑定的邀请码:
hset user:$guid boundValidators $validator1|$validator2...

那么查询的时候只需要进行两次查询:

// 查询用户名下绑定的邀请码
hset user:$guid boundValidators
// 查询邀请码是否以及被谁激活了
mget $boundValidators

为了降低网络延时,完全可以通过一个pipeline实现,从而使得网络交互从两次变成一次。

接口性能验证

由此已经大功告成,简单的使用wrk测试一下性能,服务器相比之前的差一些,一共是4核16G内存。使用wrk -t12 -c100 -d10s http:ip:port/queryActivate

海外内网、同步的redis调用:

压测结果.png

QPS在5000左右,完全满足了本次邀请码的需求,事实上,如果能超过这个量,估计睡觉都要笑醒了:)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,591评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,729评论 6 342
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,411评论 25 707
  • 1、《三言二拍》基本能读懂,主要意思的理解比较顺畅,但是有一些句子是根据上下文分析出来的,还有一些词语需要查意思或...
    孙小米阅读 257评论 1 1
  • 文章简介:今天有一个公司的人问我:“我们公司的微信公众号下周要涨粉丝1000,要求真实粉丝,能做到吗?”我的回复:...
    Robin_lian阅读 8,387评论 1 1