AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 商店
    • 问答
  • 吐槽
  • 登录/注册

系统设计问题8------打车系统/LBS

作者: 作者的头像   hpstory ,  2022-10-31 22:26:26 ,  所有人可见 ,  阅读 88


1


目录

0.基础概念
1.新鲜事–消息流的实现方式
2.用户系统(1)–缓存
2.用户系统(2)–好友关系
3.网站系统、API–翻页
3.短网址系统
4.数据库拆分和一致性哈希
5.分布式文件系统
6.分布式数据存储系统
7.聊天系统

问题:设计一款打车软件

1.明确设计需求

列举一些核心场景

  • 司机上报位置
  • 乘客发起订单
  • 匹配系统

搜索一些数值,2020年,网约车司机总数1.5M,假设每天同时在线人数约为600K
QPS = 600K / 4(假设司机每隔4秒上报一次位置) ~ 150K
峰值QPS = 150 * 3 ~ 450K
由于用户不会一直在线,QPS数量应该远小于司机,可以忽略不计。
需要记录当前位置信息 600K * 100bytes = 60M/天

2.设计服务

  • 记录车的位置 GeoService
  • 匹配打车请求 DispatchService

1.PNG

3.存储结构设计

Trip Table

Column Type Comments
id pk
rider_id fk
driver_id fk
start_lat float 起点纬度
start_lng float 起点经度
end_lat float 终点纬度
end_lng float 终点经度
created_at timestamp 创建时间
status int 订单状态

Location Table

Column Type
driver_id fk
lat float
lng float
updated_at timestamp

LBS(Location Based Service)的重点在于地理位置的存储和查询

当查询某个范围内的坐标有如下SQL:

SELECT * FROM Location
WHERE lat < myLat + delta
AND lat > myLat - delta
AND lng < myLng + delta
AND lng > myLng - delta; 

这个时候发现需要同时对两列进行范围查询,而复合索引不能同时对多列进行范围查询。
最好的解决办法是把二维坐标映射到一维。

常用的两种转换算法

  1. Google S2 简单来说就是把地址空间映射到一个整数,如果两个一维整数比较接近,对应的二维坐标就比较接近,精度较高

  2. 相对简单一点的有 GeoHash 将二维坐标映射成一个32进制的数字,两个数值的公共前缀越长,两个点约接近

world-1.png

将地球展平并划分区域,对一个地理坐标不断地迭代,得到一个二进制串,再将二进制串5位一组(刚好对应32进制)翻译成字符串(例如:9q9hvu7wbq2s),分成具体编码过程可以自行了解。

一般情况下,精度在4~6位已经足够使用了

level-1-12.png

SQL数据库

首先对geohash建立索引
查询语句SELECT * FROM Location WHERE geohash LIKE "9q9hv%";

NoSQL-Redis(推荐)

按照司机的位置分级存储,使用set数据结构
还以9q9hvu7wbq2s位置,key分别保存9q9h, 9q9hv, 9q9hvt, value保存在位置范围内司机的集合

修改后的流程如下:

3.PNG

  1. 乘客发出打车请求,服务器创建一次trip,将trip_id返回给乘客,乘客每隔几秒询问服务器是否匹配成功
  2. 服务器找到匹配的司机(通过乘客的位置计算geohash,先查6位的,如果没有再查5位。。。),写入到trip,修改订单状态,同时将Driver Table中的司机设置为不可用,并存入trip_id
  3. 司机上报位置并在Driver Table中发现有分配给自己的订单,去Trip Table中查找对应的订单返回给司机
  4. 司机接受请求,修改Driver和Trip Table中的状态,乘客匹配成功,获取司机信息
  5. 司机拒绝请求,修改Driver和Trip Table中的状态,重新匹配司机,返回第2步
  6. 订单结束后,修改Driver和Trip Table中的状态,司机设置为可用

4.拓展系统

系统的主要问题在Redis,虽然Redis有更高的读写效率,但是对于商用系统,Redis保存很多重要的数据,如果宕机,损失会非常大。

分摊流量

简单做法就是做数据库拆分,可以按照geohash或者城市维度拆分,可以减少损失

避免单点失效

  1. 主从模式,Master失效,Slave顶上,参考资料

  2. 数据持久化,参考资料

  3. 使用更强大的数据库Cassandra或者Riak

0 评论

你确定删除吗?
1024
x

© 2018-2023 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标
请输入绑定的邮箱地址
请输入注册信息