高并发GPS位置分享怎么设计实现分布式?

宇宙观光客 发布于 2013/04/15 15:22
阅读 732
收藏 4

现在要实现手机APP的接入,定时传送GPS信息作为心跳包,大概20秒一次,采用的UDP方式。

需求:要实现手机APP的人能看到周围一定范围内的其他APP手机的位置。

过去赶时间,每当上传心跳GPS包,直接扫描所有用户队列算距离推送给范围内的其他手机APP。

现在考虑到用户连接数一但上去。

首先socket推送就发送不过来,一包心跳包可能要转发给几十个其他手机APP,网卡即时流量上不去,但忙到崩了。

其次扫描队列要加锁,计算距离更需要时间,性能就上不去。

还有数据库问题,每次上传的位置都要插入数据库保存(PS:很坑爹的需求,迟早数据库塞爆,但就是要),来不及插入数据,也会影响性能,我投递到另一个专门插入DB的服务,晚点死的区别。

求助:1,怎么设计成分布式,可以多服务接入手机APP。

2,如何解决上面的问题,并满足需求。

最后,感谢所有留言回复!

加载中
0
猪圈
猪圈

1.首先DB方面及早引入Proxy层(amoeba),用户基础数据与业务数据(GPS位置,好友关系等)分库,业务数据可根据数量是否分表,业务数据实现读写分离。访问规则hash(id)。// 实例启动记得先预热数据

2.独立开辟一组业务数据缓存服务器,LRUMap实现。根据用户请求将相关业务数据逐步从DB加载到内存中(比如用户请求GPS历史位置,即加载DB所有GPS历史位置,请求好友关系,即加载DB全部好友关系)。一切数据读写以缓存为主,写数据放入队列使用线程异步回写DB。这样做的目的主要是只有冷数据才从DB加载,大大地保证了DB的读写负载,缺点是你要容忍宕机再来的数据丢失,所以要做好日志以便恢复(当然重要数据一定要实时回写)。单台15G内存机器双实例一般够支撑10w用户的热数据了。实例可以水平扩展,访问规则hash(uid)。

3.一组应用逻辑服务器专门处理网关丢过来的任务,计算完成后通知网关返回结果。比如接收到网关发过来的需要更新用户GPS位置信息指令,根据hash(uid)到对应的业务数据缓存服务器更新缓存中的GPS最新位置并返回好友关系,然后就可以根据相应的好友UID到在线缓存中查询到好友所在网关并分发通知更新的数据了。// 保持一组连接至数据缓存服务器(UDP)

4.一组网关服务器负载保持所有客户端(TCP/UDP)的连接和内部服务器(UDP)的连接

注:每组服务器均可以水平扩展,除了数据缓存服务器必须指定用户hash(UID)外,网关逻辑服务器均可用hash规则或视负载而定进行用户分配,具体支撑多少用户根据你们实际情况来定吧

         client <----req Login&response gatewayIp----> loginserver
             |
        gateway1...gatewayN
             |req logic & response data
             |
           logicserver1..N<------>dataserver1..N<-------> amoeba<-------->db1...dbN

架构差不多就是这样,不喜勿喷。码字真的好辛苦~

0
ClownFish
ClownFish
就知道入库可以用队列,其他的等待高人解析
宇宙观光客
宇宙观光客
入库队列,迟早死啊,内存就那么大,插入数据库慢,排队插入的多,队列越来越长,最后可以预见挂了。
0
宇宙观光客
宇宙观光客

引用来自“猪圈”的答案

1.首先DB方面及早引入Proxy层(amoeba),用户基础数据与业务数据(GPS位置,好友关系等)分库,业务数据可根据数量是否分表,业务数据实现读写分离。访问规则hash(id)。// 实例启动记得先预热数据

2.独立开辟一组业务数据缓存服务器,LRUMap实现。根据用户请求将相关业务数据逐步从DB加载到内存中(比如用户请求GPS历史位置,即加载DB所有GPS历史位置,请求好友关系,即加载DB全部好友关系)。一切数据读写以缓存为主,写数据放入队列使用线程异步回写DB。这样做的目的主要是只有冷数据才从DB加载,大大地保证了DB的读写负载,缺点是你要容忍宕机再来的数据丢失,所以要做好日志以便恢复(当然重要数据一定要实时回写)。单台15G内存机器双实例一般够支撑10w用户的热数据了。实例可以水平扩展,访问规则hash(uid)。

3.一组应用逻辑服务器专门处理网关丢过来的任务,计算完成后通知网关返回结果。比如接收到网关发过来的需要更新用户GPS位置信息指令,根据hash(uid)到对应的业务数据缓存服务器更新缓存中的GPS最新位置并返回好友关系,然后就可以根据相应的好友UID到在线缓存中查询到好友所在网关并分发通知更新的数据了。// 保持一组连接至数据缓存服务器(UDP)

4.一组网关服务器负载保持所有客户端(TCP/UDP)的连接和内部服务器(UDP)的连接

注:每组服务器均可以水平扩展,除了数据缓存服务器必须指定用户hash(UID)外,网关逻辑服务器均可用hash规则或视负载而定进行用户分配,具体支撑多少用户根据你们实际情况来定吧

         client <----req Login&response gatewayIp----> loginserver
             |
        gateway1...gatewayN
             |req logic & response data
             |
           logicserver1..N<------>dataserver1..N<-------> amoeba<-------->db1...dbN

架构差不多就是这样,不喜勿喷。码字真的好辛苦~

首先感谢热心回答。

关于第三点逻辑服务器组:

1.网关程序要向所有的逻辑服务器丢任务?

2.现在要做的是扫描周围一定距离的客户端,这些客户端也是实时变化或者下线了。逻辑服务器有10W用户的GPS点,当一个GPS点上来,岂不是要算10W次距离,加锁的时间太长了。这里不考虑分地域,假设都在一个城市里。

0
猪圈
猪圈

1.向负载低的逻辑服务器丢就行了,也可以根据uid来hash到固定的一台上处理。

2.其实这个就是看你算法的实现了,你完全可以再独立一组地图服务器出来(例如一个地图服务器用来处理一个城市的地图数据,大到按区,小到按县,村等)。使用基于四叉树的空间划分地图,用户上线后跟据坐标注册到相应的节点中去,离开时删除。你只要给出区域范围的坐标请求地图服务器遍历四叉树节点便可以给你返回该区域中注册的对象列表了。关键是树的深度要把握好,这就要视你应用定位的详细程度来决定了。详细参考:http://www.chinasb.org/archives/2013/01/5059.shtml

0
星爷
星爷
呵呵,可以参考游戏服务器玩家位置同步   将一个城市看做一个矩形,切分成等大的块,这样同步的时候,只需同步周围9块就可以了。根据玩家经纬度转换到对应的块就可以了。
0
宇宙观光客
宇宙观光客

引用来自“huaye2007”的答案

呵呵,可以参考游戏服务器玩家位置同步   将一个城市看做一个矩形,切分成等大的块,这样同步的时候,只需同步周围9块就可以了。根据玩家经纬度转换到对应的块就可以了。

谢谢回复!

我也这样考虑过,但会不会太忙了,最终的网络请求都汇集找这个位置服务器上了。心里很不安啊。

宇宙观光客
宇宙观光客
回复 @huaye2007 : 还真要主动通知客户端,根据GPS位置,相当麻烦,有兴趣点,要点找人,人找点。
Hansoul
Hansoul
这是个好主意,就是数据摆放时分层的想法,搜索和计算规模成指数下降,再考虑一下边界即可。这样热数据缓存+分布式既可以降低复杂度,又可以保证不遗漏。 楼主哪里?要不要试试我们的并行计算平台?说不定数据库问题也可以搞定,我这儿有bigtable。
星爷
星爷
我觉得还好,不想游戏服务器还得主动通知客户端。你就一次请求而已,况且不可能狂点查询吧!
0
宇宙观光客
宇宙观光客

引用来自“猪圈”的答案

1.向负载低的逻辑服务器丢就行了,也可以根据uid来hash到固定的一台上处理。

2.其实这个就是看你算法的实现了,你完全可以再独立一组地图服务器出来(例如一个地图服务器用来处理一个城市的地图数据,大到按区,小到按县,村等)。使用基于四叉树的空间划分地图,用户上线后跟据坐标注册到相应的节点中去,离开时删除。你只要给出区域范围的坐标请求地图服务器遍历四叉树节点便可以给你返回该区域中注册的对象列表了。关键是树的深度要把握好,这就要视你应用定位的详细程度来决定了。详细参考:http://www.chinasb.org/archives/2013/01/5059.shtml

总结一下,就是独立出一个地图数据服务器,逻辑服务器再丢到地图数据服务器,去请求周围客户端的点。

这要最终的请求都汇总在地图数据服务器,网络IO操作会很忙吧。

0
猪圈
猪圈
其实你想想,如果有一万个人都在同一个坐标范围内登陆,你不可能会将全部的人都推送给客户端吧。当然你要容纳这一万人在一颗四叉树的某个节点上一般也是不现实的,所以我们尽可能地估算一颗树的容纳人数并将该地图再按层次划分创建,相对于陌生人信息你其实仅需推送当前层次相应座标的某部分数据就行了,多层地图中数据少的层可以随机抽一张来推送相应座标内的数据一样可以。这也是游戏中的场景服务器实现,数据量的问题其实就是通过不断地细分去解决的。
小白小霸王
小白小霸王
有道理
0
北京d路飞
北京d路飞

不懂数据库,服务器性能啥的。
单从搜索周围用户算法上说一个,即使是一个城市,也同样建议划分区域。
如假设查找的是周围5km的用户,那么已5X5km为格子划分世界,每次用户上报位置后,将其归入一个格子里。这样,搜索周围用户,只要从其所在的格子及周围8个格子的用户中搜索即可。
考虑到2个用户之间相对移动进入范围的可能性,格子距离的最优值是
格子距离=搜索的半径+(20s内用户可能移动的距离的最大值X2)

返回顶部
顶部