某定时任务系统的方案设计------软件系统设计能力很重要

        来看这样一个问题:

        某账号系统的账号都在unsigned int内, 也就是0-42亿左右。 在这42亿账号中, 有大约1亿账号是相对非常活跃的用户, 用户和用户之间可以建立好友关系(类似于微信那样的好友关系)。 现在要设计一个定时赠言系统, 比如: 今天是2017年3月25日, 那么用户A可以给他的好友B送定时赠言(精确到未来某天, 不包括今天), 预期未来这天到达。而且任何用户都可以给他的多个好友多次送定时赠言。试给出合理的大致设计方案奋斗奋斗奋斗

 

        我们一起来逐步看下, 这里肯定要把定时任务先落地到存储中, 到了设定的定时日期, 读出来, 并发出去。 那存储的数据结构该怎样组织呢? 这是本问题的核心所在。

        

       方案一:

       对于每一个定时任务, 用四元组把它存起来, 即{发送者账号, 接受者账号, 定时时间, 赠言}, 对于n个赠言操作, 就有了n个四元组, 然后把这n个四元组存储起来。 然后每天都读取任务, 读取到n个四元组任务后, 根据定时时间筛选出该发送的, 发送出去。

       举个例子, 在2017年3月25日, 用户123给好友456送了定时赠言“”“I miss you”, 期望2017年3月28日到, 那么对应的四元组是{123, 456, 20170328, "I miss you"},  然后存储起来, 于是乎, 在2017年3月26日, 遍历读取存储中的众多定时任务, 发现了{123, 456, 20170328, "I miss you"}, 但时间不对,所以暂时不发。 等2017年3月27日再读取, 发现时间又不对, 所以暂时不发。 等2017年3月28日再读取, 发现时间对了, 就立即发出消息。 

       我们来审视下这个方案, 很容易发现, 这是个相当低级的设计, 2017年3月26日和2017年3月27日做了两次无用的尝试啊。 从整体来看, 这种无用次数的数量难以想象。问题显而易见, 我们没有按照时间来存储这些定时任务。 于是继续改造。

 

       方案二:

       以设定的定时时间为key, 将所有定时在这一天的任务, 落地到同一个存储区。 按照上面的例子, 简单来说就是,  以20170328为key,  于是上述赠言操作就对应一个三元组,{123, 456, "I miss you"}, 读取的时候, 按天读取任务, 然后发出。 这种方案就好多了。 但还是有问题: 三元组作为value, 有n个留言操作, 就是n个三元组的拼接, 太庞大了, 不满足系统的key value存储要求。 于是继续优化。

 

      方案三:

      以{20170328, 123}做key, 用{456, "I miss you"}做value,   这样, 通过增加key的个数,来减少value的长度。 但问题在于, 读取的时候怎么去索引呢? 难道要遍历{20170328, 0} --- {20170328, 42亿}  ? 我们要考虑到, 只有少数活跃用户啊, 这种42亿的全遍历肯定是不行的。 

      这里问题的本质是什么? 本质就是漫无目的暴力地去遍历key,  何不把有实际操作的key存下来呢? 

 

      方案四: 以20170328为一级key,  将有实际操作的用户作为value, 于是形成了这样的数据结构:20170328--->{123, 231, 101...},  其中123, 231, 101都是有实际赠言操作的用户。 然后以{20170328, 123}位作为二级key来存放 {456, "I miss you"}.  到了2017年3月28日这边, 读取操作就很顺畅了, 先读取一级value {20170328, 123}, 然后以第一级value为key读取二级value  {456, "I miss you"}..    但发现还有个问题, 二级value的值还是太大(m个二元组的拼接, 很大)。继续优化。

 

      方案五: 根据发送者尾号(比如取尾4位数)对key进行打散, 于是用户123和用户9870123的一级key就是一样的了, 都是{20170328,0123}.  该怎么读取呢? 到了2017年3月28日那边, 遍历{20170328, 0000}---{20170328, 9999}这一万个key(几乎可以肯定的是, 不会存在空遍历的情况),  于是查到123这个用户有赠言操作,于是继续用{20170328, 0123, 123}来获取到二级value  {456, "I miss you"}, 然后把消息发出。

 

       好了, 对比下方案一和方案五, 就知道优劣了。 随便说两点:

       1. 方案一没法用多进程跑读任务, 慢得蛋疼, 呵呵哒。

       2. 方案一没法在紧急情况时取消任务, 都杂糅在一起了, 取消很蛋疼的。

 

       当然, 方案的优化是无止境的, 目前来看, 方案五跑得很顺畅。 

       蛮力要不得, 任何事情, 都得讲点策略得意得意得意

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值