活码系统的技术拆解:从短链接生成到高并发分流的架构实践

5 阅读4分钟

很多开发者对活码的理解停留在“一个二维码背后绑几个员工”的层面。但作为技术人,我们需要深入到底层:当用户扫码的那一刻,系统内部发生了什么?如何保证千万级流量的稳定分发?今天,我们从架构视角拆解一套完整的活码系统。

一、活码系统的核心链路

一次典型的活码访问链路如下:

  1. 用户扫描印刷的二维码,解析出一个短链接(如 https://t.cn/abc123)。
  2. 客户端向短链接服务发起HTTP GET请求。
  3. 短链接服务重定向到企销宝的动态路由网关(携带参数 code=abc123)。
  4. 路由网关根据code获取该活码的配置(分流规则、员工池、标签策略)。
  5. 网关执行分流算法,选择一个目标员工,生成该员工的企微添加链接。
  6. 返回302重定向,用户最终跳转到企微添加页。

整个流程要求在毫秒级完成,否则会影响用户体验。

二、短链接服务的实现

短链接是活码的入口,需要考虑两个核心问题:唯一性和时效性。

生成算法: 我们采用分布式ID(雪花算法) + Base62编码,生成6-8位的短码。雪花算法保证了全局唯一性和趋势递增,方便分库分表。

存储设计: 短码到原始URL的映射存储在Redis中(热数据)和MySQL中(持久化)。Redis使用String结构,key为短码,value为原始URL,设置合理的TTL(如30天),过期后自动降级查询数据库。

高可用: 短链接服务需要无状态,水平扩展。前置Nginx做负载均衡,后端多实例部署。企销宝的短链接服务经历了多次双11大促,峰值QPS过万,稳如泰山。

三、动态路由网关的设计

网关是活码系统的核心,负责解析规则、执行分流、记录日志。

分流规则引擎: 我们设计了一套可配置的规则DSL,支持:

  • 轮询(round-robin)
  • 权重(weighted)
  • LBS(基于地理位置)
  • 时段(time-based)
  • 组合规则(如工作时间按权重,非工作时间按轮询)

规则配置存储在MySQL,缓存在Redis。网关每次请求都从Redis获取规则,若不存在则回查数据库并缓存。

分流算法实现(伪代码):

python

复制

下载

def select_employee(rule, context):
    if rule.type == 'round_robin':
        return round_robin(rule.employees)
    elif rule.type == 'weighted':
        return weighted_random(rule.employees)
    elif rule.type == 'lbs':
        return nearest_by_location(rule.employees, context.location)
    elif rule.type == 'time':
        return select_by_time(rule.employees, datetime.now())
    # 组合规则递归处理

四、高并发下的性能优化

缓存预热: 将常用的活码规则提前加载到本地缓存(Caffeine/Guava),减少Redis访问。

异步日志: 扫码日志、添加日志通过消息队列(Kafka)异步落盘,避免同步IO阻塞。

限流熔断: 针对单个活码设置访问限流(如每秒不超过1000次),超过则返回友好提示或降级页面。企销宝在网关层集成了Sentinel,实现精细化的流量控制。

五、数据一致性与最终一致性

分流过程涉及员工接待量的实时计数。我们使用Redis的原子自增操作维护每个员工的“今日已接待数”,并设置每日零点过期。当达到上限时,该员工自动从分流池移除。计数允许轻微不一致(最终一致),因为即使多分配几个,也不会造成严重后果。

六、安全防护

  • 签名校验: 所有对网关的请求携带签名,防止恶意刷码。
  • IP黑名单: 自动识别异常IP(如短时间内大量请求),加入黑名单。
  • URL白名单: 确保重定向的目标URL是企微官方域名,防止开放重定向漏洞。

结语:

活码系统看似简单,实则涉及短链接、规则引擎、高并发、数据一致性等多方面技术。企销宝的活码模块经过多次迭代,形成了稳定高效的架构。希望今天的拆解能给你带来启发。