总结:
这题不是很难,难点在于处理地理位置。把二维的转换成一维的。
应用场景:
用户搜索某个地址附近的商家信息。
用户查看某个商家的详细信息。
用户添加评论
添加新的商户信息。
Api:
public JSON( List<Location>) search(lat, lon, searchText, category, numOfResultToReturn, sortOrder)
public JSON getDetails(locationId)
public boolean addComment(locationId, contents)
public addMechant(lat, lon, LocationName, description, info), 返回一个确认号码。可以异步执行
Working Solution
用户通过load balancer 把请求发到一个web server上, web server把Lat, Lon转换成一个GeoHash。有了这个GeoHash的信息,用户先去搜索GeoHash六位精度的所有商家信息,取出来之后按用户的搜索条件去排序,返回前20条。六位的key不存在的话,就查五位的key, 再不行就查四位的key。
当用户点进去某个商家之后,服务器再跟据locationId, 去搜索这个商家的具体信息。并返回给用户。
Storage Design
Region Mechant Table 读多写少
Key Value Store: GeoHash,Set<Locations>
Location里包含 LocationId, Lon, Lat, Name, Category, Description, Star
可以用Dynamo DB, 就是简单的key value store就好了。
Location Details Table: 读多写少
LocationId, Log, Lat, Name, Category, Description, Phone, otherURLs, Other Details, Star
这个可以存sql, 也可以存在Columnar database里面。
Comments Table 读多写少。
LocationId, CommentId, Content, createdAt, Author,
可以存SQL, 也可以存NoSQL
Scale
Region Mechant Table按 GeoHash sharding, consistent sharding
Location Details Table 按 locationId sharding
Comment Table 按LocationId sharding,
Index: Comment Table按LocationId + CreatedAt 建index.
当一个地点商家太多, 就把该地点分割成更多位的GeoHash, 五位的变成6位的。同时删掉5位的。
查的时候同时query, 4, 5, 6 ,7 位, 看哪一层有值,就代表数据存在哪一层。
如何加速访问
由于信息变更很少, 加Cache最简单。 再加replica。 分在多台机器上,Consistent Hashing。
如何更新商家信息:
需要更新两张表, Region Mechant Table 和Location Table
如果有商家的LocationId(其实应该是叫Mechant Id), 则可以直接去Location Table里改,然后能过locationTable查到的GeoHash信息,再去RegionMechant信息里改。
异步执行更新,添加操作
有时加一个新的点,可能会需要涉及挪动一些数据。所以可以丢到一个message Queue里面异步执行。