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

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

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

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

  • 单个或批量的生成邀请 码,要求六位,数字与字符的混合,供运营和用户使用;

  • 给用户激活邀请 码;

  • 校验用户是否已经激活邀请 码;

  • 批量给已注册用户绑定几个可用的邀请 码,方便二次传播;

  • 查询用户名下已经绑定的邀请 码和其被激活的情况,验证二次传播的效果

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

  • 邀请 码生成算法与唯一性保证

  • 邀请 码高效查询与激活

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

邀请 码的生成方式

产品的要求是六位,同时字母和数字混合的方式,一共会发放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}; 第三步则是设置邀请 码本身的状态,即这个邀请 码被哪个用户用了,方便之后查询 

image.png

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

image.png

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

image.png

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

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

image.png

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

image.png

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

接口性能验证

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

海外内网,同步的redis调用。

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

本文转载自异步社区。

原文链接:https://www.epubit.com/articleDetails?id=NC7E3EF94036000018D9719A019301B8D

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。