高效搭建LBS与SNS结合的应用

来源:互联网 发布:广东省网络医院 接诊点 编辑:程序博客网 时间:2024/06/06 04:00

前言

本文追述LBS的前世今生,透视LBS拥有的优秀基因和继承的缺陷,从技术架构的视角对流行的LBS+SNS系统进行剖析。 – 作者:李祎

LBS基于位置的服务(Location Based Services)一直是移动开发的热门领域,各种基于LBS的移动应用层出不穷。作为应用开发者如何不雾里看花,找到最好的切入点进行技术选型和设计应用? 本文追诉LBS的前世今生,透视LBS拥有的优秀基因和继承的缺陷,从技术架构的视角对流行的LBS与SNS结合的应用进行剖析, 为打算在LBS领域创业和创新的开发者提供一些技术参考。

前世 – 源自GIS

就像认识一个人首先要了解他的家庭背景,我们先介绍一下LBS的父亲GIS 地理信息系统(Geographic Information System) 。 GIS发展于60年代,它的技术架构和传统的Client/Server信息系统没有太多区别。PC端应用程序通过网络连接后台数据库,查询和处理地理参照数据(例如大气层和地表等空间要素的位置和属性)。从技术角度来说构建一个地理信息系统,需要解决三个问题。数据如何保持,如何分析,以及怎么展现给用户。 GIS有多种展现形式,例如PC客户端,web网站(见图1),本文就不深入讨论,我们重点来研究数据如何保存,如何分析这两个问题。

map
图(1)

GIS将通过全球定位系统GPS(Global Positioning System)得到的数据,保存到空间数据库。空间数据库有别于传统的关系数据库,它补充了大量几何空间相关的功能。 主要解决存储空间中的对象数据(例如点,线和多边型);并对空间数据的特殊需求进行空间索引, 用最优的CPU和IO效率进行空间数据对象相关的查询。

空间分析是空间数据库的基础功能,它从空间物体的空间位置、联系等方面去对空间中的对象数据进行计算和空间检索。例如某个视图范围内的矩形检索,周边检索,同城搜索等空间分析功能。目前常见的商业关系数据库都有基于GIS的扩展,例如ORACLE 的spacial database ,MS SQL的空间扩展,PostgreSQL针对空间数据库的扩展 PostGIS 。常见的开源数据库 MongoDB和Mysql也支持空间数据类型的存储,但是对空间数据对象相关的检索和查询支持得非常少。

今生 – LBS+SNS

现在如火如荼的社会化网络SNS大潮,改写着互联网的格局,也冲击着LBS应用领域。特别是智能手机应用的喷井式爆发,吸引更多的掘金者把目光聚焦到LBS和SNS结合这个领域来。例如在 2012年12月,高德与新浪微博宣布战略合作,用户在使用高德地图时就可以看到自己微博足迹的文字和图片信息。

那么要如何选择技术架构搭建LBS与SNS结合的应用,来解决位置信息的存储和分析这个两个核心问题?比较现实的选择是如图2A,用PostGIS作为POI兴趣点(Point of Interest)数据的存储和查询解决方案,用Mysql + Memcache支持SNS用户数据的存储和查询,通过用户ID和POI ID把LBS和SNS这两个看似独立的系统进行数据关联起来。例如世纪佳缘,陌陌(图2B),图钉等的用户定位,还有瓜子社区根据用户位置展现周边社区消息,都适合这种架构。 通过搜索查询空间数据库来找到附近的POI信息,然后从POI中关联的用户ID信息到SNS系统中去查询用户信息, 通过接口调用交给手机端显示。
mm
图(2)A 图(2) B

下面用示例来展现如何实现“查询手机用户当前1公里范围内的陌生人”这个典型LBS与SNS结合的功能。 在PostGIS数据库中 创建表

sns_lbs_tire :CREATE TABLE sns_lbs_tire (  gid serial NOT NULL,  poi_id character varying(100),  user_id integer,  geom geometry(Point,4326),  CONSTRAINT gid_pt_pkey PRIMARY KEY (gid))WITH (  OIDS=FALSE );

表中user_id字段表示用户的唯一ID, poi_id表示POI的唯一ID, geom字段为空间数据库中的POINT类型存储POI的经纬度信息。 使用PostGIS空间数据库的分析函数,查询当前位置(-117.147605 32.715802)) 1公里范围内的所有陌生人。SQL语句 如下:

"SELECT poi_id, user_id FROM sns_lbs_tire  WHERE  + ST_Distance(ST_Transform(ST_GeomFromText('POINT(-117.147605 32.715802)',4326),26986), ST_Transform(geom,26986)) <= 1000;";

其中 4326 和 26986 是OGC标准中空间参照系统中常用的SRID

使用Java代码来实现调用postGIS数据库, 执行SQL语句查询附近陌生人用户ID列表。

import java.sql.*;import java.util.*;import java.lang.*;public class LBS2SNS {    public static void main(String[] args) {        Connection conn;        String dbname = "template_postgis_20";        String dbuser = "postgres";        String dbpass = "admin";        String dbhost = "localhost";        String dbport = "5432";        String nearbySQL = "SELECT poi_id, user_id FROM sns_lbs_tire " +                             "WHERE " +                             "ST_Distance(ST_Transform(ST_GeomFromText('POINT(-117.147605 32.715802)',4326),26986)," +                            "ST_Transform(geom,26986)) <= 1000;";        try {            Class.forName("org.postgresql.Driver");            String url = "jdbc:postgresql://" + dbhost + ":" + dbport + "/" + dbname;            conn = DriverManager.getConnection(url, dbuser, dbpass);            Statement s = conn.createStatement();            System.out.println("Querying table...");            ResultSet r = s.executeQuery(nearbySQL);            while( r.next() ) {                String poi_id =  r.getString(1);                int user_id = r.getInt(2);                System.out.println("poi_id= " + poi_id + ",user_id=" + user_ id);            }            s.close();            conn.close();        } catch( Exception e ) {            e.printStackTrace();        }    }}

得到用户ID列表后,可通过图2A中用户数据接口查询用户信息, 轻松完成图2B的前端展示。

图(2)的技术架构, 适用于千万级以下用户的LBS结合SNS的应用。当遇到需要将SNS和LBS深度结合的需求,面对海量的用户数据带来强烈的冲击,它就显得难于应付了。 例如新浪的位置微博(图3),用户使用手机发布的微博都带有经纬度坐标, 每个新的经纬度坐标都会创建一个POI。 依据新浪微博官方数据,每天产生 1亿条微博,如果50%以上的用户使用移动终端来发布,每天就有近5千万条位置微博产生。如此海量的POI数据,而且还在持续高速增长,如果使用传统GIS的空间数据库来存储,无论是PostGIS还是Oracle Spatial database, 都是无法满足存储要求和实现高效查询的。那么要如何来解决上千万用户级别的LBS+SNS应用所需要的数据存储和分析呢?
weibo
图(3)

案例分析

笔者参考了互联网上公开的资料,同时结合自己的架构经验,对新浪位置微博的系统架构进行分析。笔者认为新浪位置微博采用了和新浪微博主页的微博墙类似的系统架构。我们先来看一下新浪微博的系统架构。
新浪微博为了实现用户快速访问微博墙,将粉丝关系和用户的微博墙都放到缓存Memcached。 用户发布的微博会被推送到异步消息队列。另外一个进程从异步消息队列中取出微博,根据发布者的用户ID从缓存中取出发布者的粉丝列表,将微博ID逐一添加到每个粉丝的微博墙上, 同时更新发布者的微博墙。我们用明星成龙和姚晨发布微博来举例, 看看他们的微博是如何被粉丝甲看到的。
这里写图片描述
图(4)

  1. 成龙发布了一条微博001,姚晨发布了一条微博002。 两条微博通过http请求被送到微博发布APIserver。
  2. 微博发布APIServe将两条微博消息写到MQ消息队列。
  3. 微博消息分发模块从MQ队列取出微博消息, 将微博内容写入微博内容Memcached。 将微博001的ID 001添加到成龙的个人微博墙Memcached, 将微博002的ID 002添加到姚晨的个人微博墙Memcached。
  4. 微博消息分发模块根据成龙的ID访问用户粉丝关系Memcached找到他的粉丝ID列表。启动多线程,根据粉丝数分批次的将微博001的ID 001写到粉丝的微博墙上。根据姚晨的ID访问用户粉丝关系Memcached找到他的粉丝ID列表。将微博001的ID 002写到粉丝的微博墙上。
  5. 粉丝甲浏览自己的微博墙时, 微博浏览APIserver 根据粉丝甲的微博墙ID列表, 调用微博内容Memcached,取得微博墙的数据, 交给Apache Web Server进行最终的html页面渲染, apache Web server 将最终页面返回给粉丝甲。

新浪位置微博采用了和新浪微博非常相似的架构,区别在于位置微博把缓存(Memcached)中的用户 ID换成POI ID, 当用户发布微博时,位置微博会根据发布微博的经纬度信息生成POI ID。 当有用户要查询某个POI附近的微博时,通过附近查找算法, 找到附近的POI ID列表(类似于微博的粉丝ID列表)。由微博消息分发模块将微博ID 写入POI点的微博墙。

queue
图(5)

  1. 新浪微博通过微博消息分发模块,将MQ消息队列中的微博消息微博001,微博002分发到位置微博的MQ队列。
  2. 位置微博消息分发模块从MQ队列取出微博消息,根据微博中包含的经纬度信息计算生成POI ID, 将POI 信息保存到空间数据索引中。
  3. 微博消息分发模块取出微博001,将微博ID 001写入 西长安街POI的微博墙Memcached中。取出微博002将ID 002写入东交民巷的微博墙Memcached。
  4. 位置微博消息分发模块调用附近POI查询模块, 获得POI ID附近的POI ID列表,把微博ID 001 002写到周围的POI 的微博墙Memcached中。
  5. 当用户查看户天安门附近的微博时, 位置微博浏览APIserver根据天安门POI ID调用POI的微博墙Memcached取出微博ID列表, 然后调用微博内容Memcached 取出微博内容。交给Apache Web Server进行最终的html页面渲染, apache Web server 将最终页面返回给粉丝甲。

如上所述, 新浪微博根据自身业务的需要, 量身打造了一个完整的位置服务LBS+SNS的解决方案。要说明一下,新浪位置微博开放的位置服务API提供了:地点写入,地点读取,地点附近查询,用户LBS信息查询,位置微博动态查询等6大类接口(参见: http://open.weibo.com/wiki/位置服务), 基本满足了SNS网站功能开发的需要。对于独立应用开发者,如果并不打算把产品完全绑定在新浪微博上,这套体系并不一定适用。

百度的LBS云服务(参见: http://api.map.baidu.com/lbsapi/cloud/lbs-cloud.htm), 提供了一种完全透明的LBS+SNS解决方案。 它一方面解决服务器端日益增长的海量位置数据的存储维护压力,另一方面彻底解决基于位置数据的高并发检索瓶颈。 完全可以替代传统的空间数据库,解决基于位置数据的高并发检索瓶颈(图6)。这两个问题的解决,无异于解除了应用开发者头上的紧箍咒。唯一不足的是在实时性方面,由于存储索引和查询索引不是同步更新,百度LBS云在查询附近POI时,很可能出现不能实时查到的情况。

这里写图片描述
图(6)

总结
综上所述,随着LBS技术领域的不断发展,如何解决空间数据存储和检索查询这两个问题的技术在不断进步,涌现出了很多更好更高效的解决方案。 本文分析了在现有市场上可寻找到的技术, 对于架构一个LBS与SNS结合的应用给出了可行性的架构方案。 小型应用使用PostGIS,中型应用使用oracle spacial database 或百度LBS云, 大型应用则要根据LBS+SNS的具体需求,自己构建合适的空间索引和业务架构。

0 0
原创粉丝点击