基於Mysql5.7實現查詢附近的店鋪
我們新開發了一個電商平臺,需要實現附近的店鋪功能,經過預研,覺得沒有必要採用mongodb的地理位置查詢功能,因為涉及資料同步,還有聯合索引的問題。直接用MySQL5.7內建的距離計算功能就可以滿足大規模計算距離的需求。
計算附近的店鋪時侯,一般的需求是傳入使用者的座標,需要計算出附近的店鋪,按照使用者和店鋪的距離排序返回前端。在成千上萬家店鋪選擇附近的店鋪就涉及效率的問題了。最好的方式是先找到附近的店鋪,然後再在選定的店鋪範圍內計算距離,這樣就能大幅減少計算量。業界採用的是geohash,首先在獲取店鋪座標時候,就計算出店鋪的geohash,在使用者傳入座標後,也計算出使用者的geohash和他周圍8個區域的geohash,然後看店鋪如果在使用者周圍的geohash範圍內,才計算店鋪和使用者之間的距離。這裡有個問題,如果使用者在一個周圍都是店鋪的區域,那麼檢索的範圍可能比較小就可以拿到使用者每次翻頁所請求店鋪數了,但是如果使用者在一個周圍店鋪不多的區域內,就需要檢索一個比較大的範圍才可以拿到使用者每次翻頁所請求的店鋪數。這裡就涉及geohash的精度問題了,geohash位數越高,所表示的範圍越小,距離使用者越近,反之越遠。店鋪需要預先計算一個精度比較高的geohash,如果想要取比較大的區域,只需要店鋪的geohash like使用者的geohash前幾位就可以了.每次使用者請求的時候,前端需要告訴後臺使用者的gps座標,其他過濾條件,之前已經返回給使用者的商鋪id列表,後臺按照使用者的gps座標按照7位精度計算出使用者周圍的9個geohash區域,加上過濾條件和不需要計算的店鋪id列表,查詢一下附近的店鋪數,如果店鋪數小於前端請求的資料條數的2倍(這裡取2倍是考慮過的,假設店鋪是平均分佈的,使用者的位置比較極端,恰好在他所在的geohash的角上,這樣距離他比較近的點就在它周圍的4個區域內,其他的5個區域的點離他都比較遠,從區域的數量上來看是4:5,接近1:1吧,所以就選了2倍,應該差不多),就將計算的geohash列表的位數縮小一位,再去查詢使用者周圍的店鋪數,如果滿足條件就退出,否則一直計算到4位精度,然後用最後拿到的geohash列表和過濾條件真正去計算使用者周圍的店鋪和距離使用者的距離,返回給前端.這樣能最小化資料庫計算和排序的壓力.即使這樣,作為資料庫仍然是壓力比較大的,在這裡採用多從庫可以解決併發的問題.至此,我們實現了基於Mysql5.7查詢附近的店鋪,計算量壓縮到了極致,併發達到了無限.