第7-10天

day07

1、你们物流项目中的路线规划是怎么做的?

我们是基于Neo4j的深度查询实现的,通过指定发件人、收件人所在的网点,进行路线规划,我们实现了两个维度的规划,分别是最少转运节点和最低成本,这两种方式具体使用哪一种,是通过全局设定的参数来决定的。

2、如何确定路线的成本和距离?成本计算规则是什么?该成本会计算到公司利润核算中吗?

关于路线的距离,我们记录的是实际距离,具体的实现是通过高德地图的接口查询到的,而成本的计算是通过全局设定的每公里的成本单价*距离计算出来的,该成本仅仅用于路线规划中的成本属性,并不是实际的成本,所以不能用于公司的利润核算 。

3、对于路线的往返你们是怎么设计的?为什么成对创建的?

关于路线的设计,我们是设计的往返路线,也就是在创建路线时成对创建,这是因为我们业务的特殊性,车辆从A点开往B点,后面是需要从B点回到A点的,不能跑空车,主要是公司成本的考虑、

4、路线支持修改起点或终点机构吗?请说明理由。

不支持的。因为Neo4j中,关系是无法脱离节点存在的,如果需要修改某一个路线的起点或终点,可以先把原路线删除,再创建新的路线即可。

day08

1、MongoDB存储的数据结构与MySQL存储的数据结构有什么区别?

MongoDB与MySQL是不一样的,主要区别在于:

●MongoDB属于非关系型数据库,由于底层基于分布式文件实现,所以支持海量数据的存储,MySQL是基于本地文件系统实现,无法支持海量数据存储,MySQL可以借助于分库分表技术实现。

●MongoDB采用类似json的结构bson实现,更加的灵活,不要求每条数据的字段数量都一致,而MySQL采用传统的行列表格实现。

●MongoDB的操作更像是是调用方法完成,而MySQL采用SQL语言实现。

●MongoDB的优势在于单表操作,对于多表连接查询支持并不好,可以通过聚合函数实现,而MySQL天然的支持链表查询。

2、为什么会使用到MongoDB?MongoDB中如何存储坐标位置数据?如何实现附近的人查询?

我们在实现作业范围时用到了MongoDB,因为作业范围实际上是一组坐标点数据,由这些坐标点组成的闭合的多边形,我们需要通过一个点查找是否在这个多边形的范围内,而MySQL是做不到这一点的,MongoDB就很容易能够实现,因为MongoDB支持地理空间坐标索引,并且支持的类型比较丰富。

实现附近的人查询,主要的思路是,以当前用户的坐标点为圆心,查询距离为半径画圆,在MongoDB中查询这个圆形覆盖的数据,具体是使用NearQuery实现。

3、用户下单后如何确定为其服务的快递员?如何确定起点、终点的机构?

用户下单后,根据发件人的详细地址获取到其经纬度坐标点,收件人详细地址获取到经纬度坐标点,然后根据这两个坐标点在作业范围中进行查询,即可查询到服务范围内的快递员和机构。

4、作业范围如果不使用MongoDB,还可以使用其他技术实现吗?

不使用MongoDB的话,还可以通过Elasticsearch实现,但是Elasticsearch更擅长全文索引,实现搜索功能,虽然也能实现,但是在作业范围这个功能中使用MongoDB更适合一些。

day10

1、你简历中写的调度中心是什么意思?它有什么用?为什么要设计调度中心?

我们物流项目中的调度中心,主要是完成快递员、司机、车辆的调度工作,比如:用户下单后哪个快递员上门取件,就需要经过调度中心进行计算,给快递员分配取件任务,也就是说调度中心主要就是计算一些核心的业务逻辑,重点在于通过计算完成资源的调度工作。

2、你们物流项目核心的业务逻辑你了解吗?能画一下吗?这个是你设计的吗?你都参与哪些业务模块的开发?

我们物流项目中的核心业务逻辑我是了解的,虽然这个不是我设计的,但是我参与了一些业务的开发,我主要是参与的快递员任务分配的开发,就是用户下单之后选择在服务范围内,有排班并且当日任务量最少的那个快递员进行分配。 参考【业务分析图】

3、用户下单后,是如何确认上门取件的快递员的?如果有多个快递员怎么处理?怎么做到均衡分配任务的?

我们是通过发件人的详细地址可以确定去经纬度坐标,通过这个坐标数据就可以定位到作业范围内的快递员,如果有多个快递员我们就计算他们的快取件任务量,优先分配最少任务量的快递员,这样就可以达到均衡分配任务的效果。

4、生成取件任务,为什么会用到延时队列?

这个是产品经理在产品上的定义。就是用户期望上门时间与当前时间超过预定的时间(如2小时),就暂时不给快递员下发取件任务,这个时候就需要使用延迟队列,等到达预定时间再下发任务。

day11

1、系统分配取件任务后,如果快递员不能上门取件,你们是怎么处理的?有几个情况需要考虑?

分配给快递员的取件任务,如果快递员不能上门取件,快递员可以转给同网点的其他快递员。也可以进行取消操作,如果快递员取消必须要选择【取消原因】,系统会根据不同的【取消原因】做不同的处理,比如取消原因是【违禁品】直接关闭任务,如果是【用户取消】就将订单进行取消操作,其他原因就将订单关闭。

2、你们系统中的,订单和取派件任务是什么关系?是一对一的吗?怎么设计的?

我们设计的订单与取派件任务是一对多的关系,也就是说一个订单可能会对应多个取派件任务,因为有些任务分配给A快递员后,A不能完成任务,需要系统重新分配,这个时候就会产生多个取件任务。派件任务也是一样的道理,所以是一对多的关系。

3、派件任务是在什么时候生成的?快递员可以取消派件任务吗?为什么?

派件任务是在快递到达目的地网点时,系统会生成派件任务,快递员是不能自己取消派件任务的,如果需要需求就需要在后台系统中完成,主要是考虑到不能放快递员私自取消,避免无快递员愿意派件的情况,因为一般派件的提成比取件要低。

4、项目中有用到分布式事务吗?在什么场景下用的?具体怎么用的?

有用到。我们是在快递员上门取件后,点击【取件】操作用到了,我们是使用Seata框架的AT模式实现的,

快递员微服务中取件成功后需要调用订单微服务修改订单的状态、需要调用任务微服务修改取件任务的状态

方法上加了@GlobalTransactional注解,这样就开启分布式事务,起到了全局事务的作用,确保了跨多个微服务更新操作时,可以做到同时成功或失败。

day12

1、物流项目中你参与了核心的功能开发吗?能说一下核心的业务逻辑吗?

我在物流项目中参与了部分核心功能的开发,比如在智能调度中我参与了【订单转运单】的业务开发。订单转运单是在快递员取件成功后,将订单转为正式的运单,也就意味着即将开始真正的运输,在生成运单编号时我们采用了美团Leaf来生成自增长的单号,并且性能方面有保障。在实现中,使用消息与其他微服务交互,并且确保了接口的幂等性。

2、你们的运单号是怎么生成的?如何确保性能?

运单号采用了美团Leaf来生成自增长的单号,美团Leaf是一个开源的高性能的ID生成服务,其底层采用双buffer模式确保了性能。双buffer的方式:Leaf服务内部有两个号段缓存区segment。当前号段已下发10%时,如果下一个号段未更新,则另启一个更新线程去更新下一个号段。当前号段全部下发完后,如果下个号段准备好了则切换到下个号段为当前segment接着下发,循环往复。

3、能说一下订单转运单的业务逻辑吗?生成运单后如何与调度中心整合在一起的?

订单转运单是在快递员取件成功后,将订单转为正式的运单,也就意味着即将开始真正的运输。生成运单后与调度中心整合,我们采用的是MQ消息的方式进行整合的。

4、合并运单为什么使用Redis的List作为队列?如何确保消息的幂等性的?

之所以选择使用Redis得List作为队列,是因为我们需要一个高性能的、先进先出的队列,所以使用Redis是不错的选择,具体实现的时候,我们采用的左进右出。为了确保运单处理的幂等性,我们采用Redis的set结构存储该队列中对于的运单,将运单加入队列时,先经过set集合进行判断是否存在,如果存在就不加入,否则才加入。

day13-智能调度之运输任务

1、能说一下xxl-job的分片式调度是在什么场景下使用的吗?这样做的好处是什么?

一般使用xxl-job的分片式调度,是需要并行处理大量数据或任务时用到,使用分片式调度的好处就是充分利用分布式资源,多台服务器并行执行任务,并且确保数据的不重复处理。

2、有用过分布式事务吗?你们是怎么用的?用在什么场景?

有用到。我们是在快递员上门取件后,点击【取件】操作用到了,在快递员微服务中调用任务微服务修改取派件任务状态、调用订单微服务修改订单的状态

我们是使用Seata框架实现的,主要是在取件的方法上加了@GlobalTransactional注解,这样就开启分布式事务,起到了全局事务的作用,确保了跨多个微服务更新操作时,可以做到同时成功或失败。

AT:执行SQL事务提交、记录快照到undolog表中

XA:执行SQL事务不提交、等所有的SQL都执行后统一提交或回滚

TCC:和AT原理说一样的,快照表需要我们自己维护的

3、不同的运单流转节点是不一样的,你们如何将运单合并?如何确保redis的高可用?

在合并运单实现中,我们将运单存入到待处理的队列中,待处理的队列采用Redis的List实现,key为:当前机构id+下一个机构id,采用左进右出的方式将运单数据存入到队列。redis的高可用我们一般优先采用redis的主从架构+哨兵模式,如果数据量大的情况下,会考虑使用redis分片模式。

redis的主从架构:不能自动故障恢复

哨兵模式:建立在主从基础上、可以帮助主从自动故障恢复

分片:多个主 每个主都有从

4、你们系统中,车辆、车次和路线之间是什么关系?车辆有司机数量限制吗?

车辆、车次和路线之间的关系是这样的,在一条路线上可以绑定多个车次,每个车次可以绑定一个车辆,每个车辆必须至少两个司机,并且司机的基本信息必须的完善的。

day14

你们项目中的物流信息那块存储是怎么做的?为什么要选择MongoDB?

1、如果采用MySQL实现的话,MySQL存储在一张表中,每条物流信息就是一条行数据,数据条数将是运单数量的数倍,查询时需要通过运单id作为条件,按照时间正序排序得到所有的结果,而MongoDB存储基于其自身特点可以将物流信息列表存储到属性中,数据量等于运单量,查询时只需要按照运单id查询即可。所以,使用MongoDB存储更适合物流信息这样的场景,我们将基于MongoDB进行实现。

简单来说:MySql一个运单需要有很多天物流信息数据,MongoDB一个运单只需要一条物流信息数据

2、针对于查询并发高的问题你们是怎么解决的?有用多级缓存吗?具体是怎么用的?

我在物流信息业务实现中解决过该并发的问题,由于业务的特点,用户查询的数据是具备一定的时效性的,并且物流信息更新的也不频繁,所以,我采用了多级缓存的解决方案来应对高并发,我在第一版本的实现中,将caffeine作为一级缓存,redis作为二级缓存,如果一级缓存能够命中就返回数据,否则进行二级缓存的命中,最终兜底的是MongoDB。

3、多级缓存间的数据不一致是如何解决的?

多级缓存间的数据不一致问题,在我开发过程中有遇到过的,我的解决方案是通过Redis的发布订阅功能实现,具体是在更新二级缓存时向redis发出消息,所有的服务节点都监听该队列,所有的服务节点就会收到更新的消息,然后将自身一级缓存中的数据删除即可。

4、说说在使用Redis场景中的缓存击穿、缓存雪崩、缓存穿透都是啥意思?对应的解决方案是啥?实际你解决过哪个问题?

缓存击穿是指,某一热点数据存储到redis中,该数据处于高并发场景下,如果此时该key过期失效,这样就会有大量的并发请求进入到数据库,对数据库产生大的压力,甚至会压垮数据库。

缓存雪崩的情况往往是由两种情况产生:情况1:由于大量 key 设置了相同的过期时间(数据在缓存和数据库都存在),一旦到达过期时间点,这些 key 集体失效,造成访问这些 key 的请求全部进入数据库。情况2:Redis 实例宕机,大量请求进入数据库

缓存穿透是指,如果一个 key 在缓存和数据库都不存在,那么访问这个 key 每次都会进入数据库很可能被恶意请求利用缓存雪崩与缓存击穿都是数据库中有,但缓存暂时缺失缓存雪崩与缓存击穿都能自然恢复,但缓存穿透则不能

我实际解决了缓存穿透的问题,主要是应用布隆过滤器解决,在进行缓存命中之前先进行布隆过滤器的判断,如果不存在直接返回,如果存在再进行缓存命中。

5、说说布隆过滤器的优缺点是什么?什么样的场景适合使用布隆过滤器?

布隆过滤器的优缺点:

优点

○ 存储的二进制数据,1或0,不存储真实数据,空间占用比较小且安全。 512M--->42亿多

○ 插入和查询速度非常快,因为是基于数组下标的,类似HashMap,其时间复杂度是O(K),其中k是指哈希算法个数。

缺点

○ 存在误判,可以通过增加哈希算法个数降低误判率,不能完全避免误判。

○ 删除困难,因为一个位置可能会代表多个值,不能做删除。布隆过滤器适合判断数据一定不存在,不适合判断一定存在的场景。

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值