项目总结,路径匹配的业务逻辑

打车项目的难点

首先它是一个SpringCloud项目,分为7大模块

网关模块JWT令牌校验,请求的路由转发,

account模块我们的一些人员注册,增删改查乘车人

stroke路径模块做的一个行程的路径匹配,以及面对超时回复的时候,情况的处理

order订单模块行程一些比如说计费,多少米什么的信息

pay支付模块:需要进行微信支付的沙箱模拟操作,以及一些沙箱的回调。

首先我们发布行程,会有一个hash来存储对应的key是字符串+用户的ID,value 经度纬度

两端的位置如何定位与记录

双方形成的坐标匹配如何设计

对话实时通讯

匹配成功后,司机座位数的统计

司机发出邀请之后,乘客无响应如何处理

高并发的行程数据的实时坐标如何记录和同步

计算选型

后端:springcloud+nacos+gateway+feign

前端:nginx,动静分离

存储基本业务数据mysql+即时位置geo(redis距离运算,,)mongodb(车辆位置,并不涉及过多位置计算,比如车辆到达那些位置)

缓存:redis,难在缓存如何设计上

消息:rabbit+kafka+websocket

前段h5+css+jquerymobile,地图对接,websocket,接口通用

注册中心nacos,服务网关:gateway,

行程中心stoke订单中心order

用户中心account,支付中心payment,存储中心storage,消息中心:notice.

mysql,或许也是可以的用户和商家距离,用户很多,Point(120,30) 可以使用一个where lat beween a-x and a+x and long between b-y and b+y,需要用一个联合索引(latitude,longtitude)

筛选后,使用聚合函数,进行一个排序

select id,acos()*cos...as distance from t having distance<1 order by distance asc limit 0,20.

分布式

雪花算法snowflake是一种优秀的分布式ID生成方案,其优点突出:它能生成全局唯一且递增的ID,确保了数据的一致性和准确性;同时,该算法灵活性强,可自定义各部分bit位,满足不同业务场景的需求;此外,雪花算法生成ID的速度快,效率高,能有效应对高并发场景,是分布式系统中不可或缺的组件。

第一位是标记(由于long基本类型在Java中是带符号的,最高位是符号位,0或者1)默认是0,41位是时间戳

WrapObjectFactory-赋值工具,通过拦截器,通过AccountVo根据ID号来赋值

自定义注解@RequestInitial实现,id借助@InitialResolver注解+雪花Resolver生成

从Request拦截她,只要是带@RequestInitial,再去找参数。

附件表:一个是,生成文件的md5,每次上传fastdfs前比对md5信息。避免重复上传造成空间浪费,而且慢,

mongo:

notice表:放到的是即使消息,与坐标数据,

location:司机与乘客行程轨迹。

业务库:起始点

消息

kafka场景:监控数据,超高吞吐量场景,司机运行轨迹数据,发布行程的数据,可以送入kafks,进入监控大屏等展示操作

rabbitMQ场景:乘客迟迟不响应,所以采用死信队列,超时队列(超时之后,进入死信)

实时的位置数据(高并发发送实时坐标,削峰处理),websocket+mongo存储+多线程轮询扫描标记已读情况。

缓存

乘客:每个行程,司机:每个行程

匹配度计算:

zset:保存的对应行程的按照匹配度分值的进行排名,我们排行中以列表页的形式展示

map:保存我们的距离数据,用来显示车辆距离起点终点距离我们有多远

zset:10,98.22    按照匹配度排名(行程id号。 得分)

Map:10,1.2:1.1(距离起点和终点距离)

w=(a*w1+b*w2)/(w1+w2)             -不是整数,而是百分比.

1-(中心点距离起点的公里数*0.5+中心点距离终点的公里数*0.5)/半径的范围))*100

他们的哈希:名字是司机,然后键是乘客(司机存储的话)

GEO哈希编码规则

每一个字符串代表某一矩形区域,这个矩形区域的点都共享相同的GeoHash字符串,这样既可以保护隐私,又比较容易缓存

GEO原理

整个地图所分割区域进行划分,采用base32编码方式,每个字母或者数字都由5bit组成

5bit可以有32种不同组合,这样我们可以将整个地图分为32个区域,通过00000~11111来标识这32个区域五个位置,一部分给经度一部分给纬度。奇数表示的维度序列,偶数是经度序列,进行第一次划分的时候,Geohash0,1前5个bit,3bit表示经度,2bit表示维度(从0位置开始数呗)当一个乘客,选择好起点与终点的时候,

生成STROKE_PASSENTER_GEO_END

STROKE_PASSENGER_GEO_START 

司机发布行程

STROKE_DRIVER_GEO_START

STROKE_DRIVER_GEO_END

我们的操作

先放自己的,然后找到对方的行程,也要把我加进去

STROKE_GEO_ZSET_xxx(行程ID)乘客看司机时候,看的是司机的分

STROKE_GEO_DISTANCE_(行程ID)这里面的key都是和行程ID不同的

假如行程ID是乘客的,那么他的key就是司机

匹配相关用户的行程

行程匹配度排行

车主发起邀请,乘客接受/拒绝邀请

剩余座位判断

邀请超时取消

路径计算

计费-装饰者模式

空座数:座位数有限,采用记账(因为不止有加加减减,还有一些超时的)

避免i--的假如不来还要加回去座位的问题,我直接选择i++,我开始知道一共多少个位置,使用redis的hash来保存,进行一个i++,此时就是键,1,然后我们取出来是开始4个,4-获取hash的value(加就肯定是加

redisHelper.addzset(HitchConstants.STOKE_GEO_ZSET_PREFIX,hitchGeoBo.getTargetID()(乘客ID),stroke.getId()->(司机的ID),getscore(hitchGeoBo);

邀请乘客信息

如果他不这样乘客这里存储司机的ID,我们会发现假如再来一个司机,他是无法获取最新的司机消息,因为他是根据键获取的,假如我们不去添加,像是一个哈希表

哈希名称HitchConstants.STOKE_GEO_ZSET_PREFIX.100乘客ID(这就相当于hash名字)

我们是根据这个key来获取最新的司机,同时司机也会存储对应的乘客。

假如司机是480,存储的乘客720,然后value是状态吗(0,3)

720也存储对应的480,value

类似于NACOS的服务注册和服务发现

邀请流程图,

行程ID是司机的,key就是乘客。

0:未确认

1:已确认

2:已拒绝

3:已超时

STROKE_INVITE_行程ID: 对方ID 邀请状态,每次都一对关系,

​​​​​​​

超时(轮询,定时器,死信队列)

放一个生产者->缓冲队列(行程的邀请关系,超时逻辑TTL,如果超时了,会自动扔给另一个队列)->DLX(死信队列)(过期之后,通过死信队列DLX发送给实际消费队列->实际消费队列.->消费者(假如是DLX转发的话,就把状态改为超时。

调用rabbitMqTemplate

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狗哥不是甜妹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值