网约车派单之筛选司机

乘客通过网约车下单,以订单上车点为中心,筛选周围满足条件的司机。筛选条件主要有如下维度:

1. 位置筛选   考虑到导航距离筛选,需要结合路况,成本较高,一般先直接距离筛选,以订单起始点坐标为中心画圆,查询半径 radius内的司机

2. 司机基本信息筛选   如司机状态、车辆车型、司机心跳、服务城市等

3. 复杂信息筛选   如限行策略、合规策略、特定区域满足特定条件的司机筛选等

 

复杂信息筛选,这里使用责任链接模式,每个节点调用相关的第三方服务,做好timeout设置及降级策略。下文主要讨论的是条例1和条例2的架构优化。

初始架构:

       司机每隔5s上传心跳信息及实时坐标 ,更新到mongodb中,司机基本信息也存储在mongodb中,通过2d索引+多条件,查询出满足条件的司机。目前司机总量在100W+,性能压力大,体现在1. geo查询慢    2.查询条件太多

 

架构优化:

     位置信息使用redis geo索引(也可以使用google空间索引,全内存操作)。即司机上报位置信息时,只记录待服务的司机坐标并查询其最新的必要信息,使用geoAdd添加到redis中,司机必要的基本信息序列化作为member存储。key通过城市ID区分。考虑到部分司机直接杀掉客户端,心跳位置信息长时间不更新,这类司机应该清理出redis geo以减轻geo查询的压力. 因此需要记录一下最后的心跳时间,在geoAdd时,可以通过zset顺便记录一下司机的最后心跳时间,定时任务查询出n分钟内无心跳的司机信息并将其从geo中清除。通过geoRadius查询出满足位置条件的司机信息后,在内存中执行基本信息的二次筛选操作。

 

压力分析:

      redis cluster 4主4从,单机4G内存,千兆带宽。这个集群主要使用的redis数据结构为geo和zset。geo的增删改查压力较大,单机geo+zset承压峰值为6000. 6000*4=24000. 司机轨迹上传qps峰值约为5000(去除非服务中的司机可适当降低),预估geoAdd和zadd的qps为1W. 目前派单qps约为100,预约单只走一轮,即筛选一次司机。 即时单多轮筛选。估计查询qps压力为100*5.  zset范围定时查询并从geo中删除过期心跳的司机信息。这个qps预估500. 总预估qps约为12000左右。

注意点:

          1.geo和zset中的member存储的是司机的基本信息,如果只存储driverId,那么需要筛选后从mongodb或mysql中查询司机的信息然后再在内存中二次过滤。但这里需要in (driverId,driverId,driverId.......)性能会受到一定的影响。 同时注意尽量拉取出司机信息内存中做过滤,而不要使用where条件走db或nosql的过滤。

          2.从geo中查询出来的是有序的司机(距离由近及远),筛选后再走过滤链,即时单采用强绑,绑定概率较大,因此可以根据经验分开走过滤链。如筛选出1000个司机,先取出前20走过滤链,没有合适的,再接20个,减轻后续过滤链中批量操作的压力,同时可根据历史经验,动态调整“20”的值的大小。

          3.这组redis cluster 存储的key比较少,城市维度的,每个城市一个geo,一个zset。redis cluster根据slot将这些key平均分配到不同的机器上,但因为每个城市的热度不同,很有可能会导致top5的城市集中到一台 redis客户端上,这样会导致某台机器压力过大。有点类似热点缓存的问题。解决热点缓存常用两种思路: 1)使用二级缓存  内存+缓存,使用google cache本地缓存一份,或者 热点缓存+缓存,热点key单独缓存并使用哨兵模式。  2)使用key+随机数,争取让热点缓存路由到更多的机器上,来分摊压力。  但是本例中有些特别,即这个缓存key,更新的频度很高,可以事前选出top20的机器,查看是否分配均匀,如果不均匀,改变key的格式,多次重试尽量争取分散到不同的机器 。

         4.从筛选司机到最后绑定司机这段时间内,司机的基本信息可以发生变化,如司机可能收车了。即存在并发,考虑到司机属性的变化 ,涉及到不同的组别,不同的人员,使用不同的缓存及锁机制,因此可以作个后期补偿。即绑定司机后,立即查询一下司机事件,如果在N秒内,有可能影响的事件如司机收车了或者订单冲突了,自动改派或者客服手动改派。

        5. 绑司机时加分布式锁,避免短时间并发多单同时绑定同一司机

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值