跨院区陪诊预约小程序多区域调度设计
很多大型医院拥有多个院区,院区之间距离较远,陪诊订单如果直接全域检索陪诊师,容易出现远距离派单、通勤超时、陪诊师档期冲突、区域供需失衡的问题。多区域调度核心思路是先院内/片区优先、相邻院区弹性支援、全域兜底人工调度,配合区域围栏、陪诊师服务片区、区域负载水位,实现分圈层的梯度派单。本文基于Java后端实践,讲解多院区场景下的区域模型、分层调度流程、Redis GEO检索、负载均衡、跨区补贴整套落地方案。
业务痛点分析
院区之间地理隔离,不做片区限制,订单优先匹配很远院区的陪诊师,路上耗时过长,服务迟到。
区域供需不均衡,热门院区高峰期陪诊师饱和,隔壁院区陪诊师空闲,但系统不会自动调度支援。
陪诊师只能固定绑定单个院区,无法配置多院区可服务范围,资源利用率低。
跨院区订单没有通勤时长校验,没有提前预留赶路缓冲时间,导致订单时间冲突。
缺少区域负载看板,运营无法直观看到各个院区订单积压、在岗陪诊师饱和度。
跨区支援缺少激励规则,陪诊师不愿意跨院区接单,调度策略在算法上可行,但实际没人接单。
整体方案设计思路
采用圈层式梯度调度架构,划分本院区池、相邻院区池、全域兜底池三层候选池,按顺序依次尝试派单。
技术栈使用SpringBoot、MyBatis Plus,Redis GEO维护陪诊师点位与院区坐标,Redis维护区域水位、陪诊师档期锁,MQ处理订单推送、区域负载预警,MySQL存储院区信息、区域围栏、陪诊师服务片区配置。
调度链路:用户选择院区下单 → 系统锁定院区所属片区,计算订单预约时间的通勤缓冲时长 → 优先从本院区候选池匹配陪诊师;本区域饱和度超标或者无空闲陪诊师,自动扩容到相邻院区池;相邻院区也无人接单,进入全域抢单池并标记跨区订单;后台调度看板实时展示各院区负载,支持人工定向调配。
调度规则全部后台可视化配置,片区边界、相邻关系、通勤缓冲、跨区溢价系数、饱和度阈值都不需要改代码。
院区片区与电子围栏模型
每一个院区作为基础调度单元,多个邻近院区可以合并成一个调度片区,后台支持多边形电子围栏绘制,也可以配置圆形服务半径。
陪诊师不再只能绑定单一院区,支持配置多院区白名单,同时设置最大跨区通勤距离、是否接受跨院区订单。
核心字段:院区ID、片区编码、经纬度坐标、相邻片区列表、饱和阈值(在岗人数/待派订单比例)、跨区补贴比例、通勤缓冲时长。
区域负载水位分为空闲、正常、紧张、爆满四个等级,水位由当前待派订单数量、空闲陪诊人数计算得出,作为是否开启相邻片区支援的触发条件。
Redis GEO把所有陪诊师坐标写入对应片区的GEO集合,查询时优先在本片区GEO集合检索,减少无效距离计算。
分层调度引擎核心代码示例
@Service public class ZoneDispatchEngine { @Autowired private EscortGeoRepository escortGeoRepository; @Autowired private ZoneConfigMapper zoneConfigMapper; @Autowired private EscortScheduleService scheduleService; /** * 分层获取候选陪诊师 * @param orderDTO 预约订单 * @return 符合条件的陪诊列表 */ public List<EscortScoreDTO> matchEscortByZone(OrderDTO orderDTO) { ZoneConfigDO zone = zoneConfigMapper.selectByHospitalId(orderDTO.getHospitalId()); List<EscortScoreDTO> candidateList = new ArrayList<>(); // 第一层:本院区片区池 candidateList = queryZoneEscort(zone.getZoneCode(), orderDTO); if (!CollectionUtils.isEmpty(candidateList)) { return candidateList; } // 判断片区负载,达到阈值才开启相邻片区调度 boolean needNeighborSupport = checkZoneLoad(zone.getZoneCode()); if (needNeighborSupport && zone.getNeighborZoneList() != null) { for (String neighborZone : zone.getNeighborZoneList()) { List<EscortScoreDTO> neighborList = queryZoneEscort(neighborZone, orderDTO); candidateList.addAll(neighborList); if (candidateList.size() > 5) { break; } } } // 相邻片区依然无匹配,返回空,流转到全域抢单池 return candidateList; } private List<EscortScoreDTO> queryZoneEscort(String zoneCode, OrderDTO orderDTO) { // GEO检索片区内一定半径范围内陪诊师 List<EscortDO> geoList = escortGeoRepository.searchByZone(zoneCode, orderDTO.getLon(), orderDTO.getLat(), zoneCode); // 过滤时段空闲、资质正常、允许跨区标记 List<EscortDO> availableList = geoList.stream() .filter(escort -> scheduleService.checkTimeAvailable(escort.getId(), orderDTO.getAppointTime(), orderDTO.getEndTime())) .filter(escort -> { if (zoneCode.equals(orderDTO.getZoneCode())) { return true; } return escort.getAcceptCrossZone(); }).collect(Collectors.toList()); // 距离、服务分、负载打分排序 return buildScoreList(availableList, orderDTO); } private boolean checkZoneLoad(String zoneCode) { // 读取Redis中片区负载水位 String loadKey = "escort:zone:load:" + zoneCode; BigDecimal loadRate = (BigDecimal) redisTemplate.opsForValue().get(loadKey); return loadRate.compareTo(new BigDecimal("0.85")) >= 0; } }跨院区匹配到的陪诊师,订单标记cross_zone=1,自动附加交通补贴,补贴金额后台按片区配置。
通勤时间校验与档期保护
跨院区订单最大风险是赶路迟到,调度时增加通勤时长预校验。
流程:获取陪诊师当前位置/常驻点位到目标院区的预估通勤时间;预约开始时间减去通勤时间,作为陪诊师必须出发的时间;如果陪诊师上一单的结束时间晚于出发时间,直接过滤,不纳入候选。
档期锁粒度升级,不再只锁定预约服务时段,同时预留通勤缓冲窗口,缓冲窗口内不能再派其他远距离订单。
缓冲时长可按院区之间距离动态配置,院区近设置15分钟,远距离院区设置30~60分钟缓冲。
区域负载统计与调度看板
定时任务按片区统计指标,写入Redis,用于调度判断和运营监控:
片区指标:待派订单数、空闲陪诊师数量、在岗陪诊、接单率、平均接单等待时长、跨区订单占比。
负载率计算公式:待派订单 / 有效空闲陪诊人数,超过阈值自动开启相邻片区支援。
运营看板按片区色块展示水位,爆满区域标红,支持一键开启人工调度、手动下发支援通知给周边陪诊师。
高峰期支持弹性激励:爆满片区的跨区订单上浮补贴,吸引陪诊师主动过来支援。
跨区订单流转与通知策略
- 本片区候选池推送超时无人接单,自动进入相邻片区;
- 相邻片区推送同样超时,订单打上跨区标签,进入全域抢单池;
- 陪诊师抢单时前端明确展示跨院区标识、预估通勤时长、补贴金额;
- 接单成功之后,消息通知重点提醒出发时间、通勤路线;
- 跨区订单爽约规则差异化,区分是本院区订单还是跨院区支援订单,扣分权重不同。
数据表核心设计
hospital_zone:院区片区配置表,院区ID、片区编码、坐标、相邻片区、饱和阈值、跨区补贴比例。
escort_zone_rel:陪诊师片区关联表,陪诊师ID、片区编码、是否允许跨区、最大通勤距离。
zone_load_record:片区负载快照表,片区编码、统计时间、待派订单数、空闲陪诊数量、负载率。
escort_order:订单主表,增加zone_code、cross_zone、commute_minute、cross_subsidy字段。
zone_dispatch_log:调度日志,订单号、候选片区列表、调度阶段、匹配陪诊师、调度结果。
落地避坑总结
Redis GEO只做粗筛,距离打分和预估通勤时间优先使用地图路线距离,不要直接使用直线距离,院区之间有高架桥、河流,直线距离没有参考意义。
相邻片区配置不能无限递归,最多向外扩展一层,避免扩散成全域检索,失去分区调度的意义。
陪诊师位置是低频上报,不能强依赖实时GPS,以陪诊师常驻片区点位兜底计算通勤时间。
跨区补贴规则要清晰,补贴金额、结算归属记录在订单快照,对账和佣金结算避免纠纷。
片区划分不要太细碎,片区过多会增加配置成本,优先以医院院区、大型医疗集群作为调度单元。
上线先开启日志观察模式,只记录分层匹配结果,不自动开启跨区调度,观察一段时间接单率、迟到率之后再放开自动跨区策略。
这套圈层调度方案适合拥有多个分院、医联体的陪诊平台,在控制通勤风险的前提下,盘活相邻院区闲置陪诊人力,平衡各个院区的订单压力,后续可以扩展需求预测、提前引导陪诊师向压力大的院区流动。