具体需求
具体思考
- 如何判断它进入了A城市
- 15天内的新增人员应该只是极少数,绝大多数手机号估计已经发过短信了
- APP干万级用户,其中绝大多数是不会离开当前城市的
- 一天一个用户可能经过多个城市,例如坐火车A->B->C,假设全国40个主要城市
计算过程
肯定不是单点,因为每秒7万的数据量,所以采用集群模式。
采用拉取的方式,这样吞吐量和处理的速度会更快。分摊给不同的消费者,进而来降低每个服务器的处理压力。、
使用布隆过滤器,布隆过滤器是一个数据结构和一套算法。所以它是可以被存储到Redis当中的。因为Redis利用内存的高吞吐,它的并发量会更快。同时作为单台Redis,我们要进行业务处理的时候,也是扛不住的。因为前面的输入量太大。
所以Redis构建的是这种一主多从的Sentinel集群。它的主服务器主要是负责写入的,当然也可以承担一部分读取的工作。多台从属服务器可以起到流量分发的作用。
它的具体逻辑是在我们进行短信服务,在接入的时候,我们自己增加一个配置的路由列表。这里128、129、130对应了咱们这里三台服务器。同时IP地址后面会增加它的角色。wr代表的是可读可写,r代表只读(也就是从属服务器)。
短信服务会以随机的方式,从三个Redis节点中选一个出来,来进行访问。相同于就把流量以随机的方式进行了分担。当然,你不希望主服务器提供读取的话,把其变为只写就可以了。
相同于当前这个模式。做了一个读写分离的工作,未来请求量大的时候,我们只需要去增加从属节点就可以分摊压力了。这是在流量层面上做的事情。
在每个Redis中,因为在每个布隆过滤器,它作为数据结构,它是存储在了Redis的内存当中的。所以一旦布隆过滤器内容发生变化,它会从主服务器向从属服务器进行内容的同步。
布隆过滤器可以拦截绝大多数已经访问过的请求,这样布隆过滤器就能判断这个人15天内来没来过。
需要异步投递到运行商网关,因为运行商网关的响应速度比较慢,有可能需要1s或者2s等。
设计要点
布隆过滤器是一个bitmap,它占用的内存是非常非常少的,假设40座城市,占用内存计算:
布隆过滤器有小概率漏判的情况,但可以接收,布隆过滤器内存占用极少,千万级用户,可以设置100万位。漏判率很低。
为每一个城市设置一个布隆过滤器,包含最近十五天来过该城市的数据。
每天0点重新创建每一个城市的布隆过滤器,将过期手机号剔除。
短信服务消费者采用集群模式+拉取方式接收数据,保证利用集群特性分摊流量,同时利用拉取方式批量接收数据。
短信服务自建路由规则,均摊布隆过滤器访问压力。
短信发送也可以采用批量方式,比如缓存每30秒后批量向短信网关发送以提高效率。
Redis主从同步一致间隙问题会存在,但并不严重,在新增发送短信记录的逻辑中加入“近期防重发”的逻辑判断即可。
发送失败没关系,做一个任务调度过小段时间重试即可。
运营商网关没有提供回调接口,过小段时间获取短信发送状态。