二维码生成设计方案

前端动态生成

利用qrcode.js就可以在前端动态生成二维码。

好处:所有二维码动态生成,不用存储静态文件。

不足:

  • 在不对链接做处理的情况下,如果链接很长,二维码信息多,会造成生成的二维码图片“密密麻麻”,在远距离/弱光环境下无法扫
  • 因为不是二维码图片,所以只能截图分享,操作成本高

前端动态生成 + 短链接服务

利用短链接服务,可以将长链接转换为短链接,再生成二维码。

用户扫码后,会进入短链接,进行一次查询,得到对应的长链接,再跳转到长链接。

好处:

  • 所有二维码动态生成,不用存储静态文件
  • 由于是短链接,信息少,所以二维码非常清晰

不足:

  • 因为不是二维码图片,所以只能截图分享,操作成本高
  • 短链接作为中台服务,域名通常不会变动。当其它业务使用短链接,不合规造成域名被封,那么二维码就无法使用

前端动态生成 + 存储参数(本质还是短链接)

不同于短链接服务,利用另一种思路缩短链接,来降低二维码复杂度。

将长链接的参数存储到 DB 中,并且给此条记录分配一个 param_id。在生成二维码的时候,只需要使用path+param_id拼接的 url 即可。

不足:

  • 用户在扫码二维码的时候,需要根据 param_id 做多一次查询
  • 参数千变万化,虽然可以利用字段排序来减少重复参数的数量,但是存储的记录依然非常多。并且随着业务发展,这些参数含义可能过时,浪费存储。

静态生成 + 存储参数

动态生成的问题
不论哪种动态生成,都不能既保证 CDN 缓存命中率(链接都不相同),又保证低成本分享门槛(用户需要截屏)。

如果只是单纯的静态生成,也就是说生成二维码图片,存储到 cdn,用户可以直接访问 cdn,得到二维码图片。虽然这个分享,但是存在以下几个问题:

  • 不同业务、不同参数、不同链接。二维码都是不相同的,要存储很多资源。
  • 过期业务、过期接口,生成的二维码都是没用的,浪费存储资源。
  • 对于高峰期或者热点业务,新的参数和 API 会有新的二维码生成,导致无法预热缓存。
  • 怎么解决以上问题?就是借助在 DB 中“存储参数”的思路解决。解决思路的本质是创建个 Pool(池),里面囤积的是 param_id。

假设 Pool 大小是 10w,假设业务的 path 是相对固定的,二维码的信息是:path+param_id

那么可以先针对 Pool 中 param_id,生成对应的 10w 个二维码,并且进行缓存。

在给用户生成二维码的时候,就从 Pool 中找到没有对应参数的 param_id,为其设置记录,并且返回其二维码图片地址(已经在 CDN 了)。

当参数没用的时候,比如交易完成,那么将 param_id 记录对应的参数设为空,此 param_id 被释放,重回 db。但是对应的二维码还是在 cdn,等 param_id 有对应参数的时候,可以再次使用。

二维码囤积方式
1、夜间生成,白天复用
2、工作日生成,周末高峰期复用
3、白天捡漏

问题的价值

问题的价值在于如何生成命中率高的静态资源,并且静态资源能复用,代表不同的业务含义。

参考链接