基於中臺思想的物流系統設計(三):構建物流地址能力

1、引言

在電商物流領域咱們會涉及到地址,其中包括了基礎的四級地址和用戶填寫的地址。四級地址在整個從下單到收貨的業務流程中都會用到,所以設計的時候要考慮如何最大限度地提升QPS。用戶地址在下單的時候讓用戶填寫或者選擇,而後存在交易訂單和物流訂單上,後續的流程通常不會變,若是用戶須要修改地址,直接變動交易訂單和物流訂單的地址信息便可,所以設計的時候主要考慮知足各類用戶地址場景。

2、物流地址數據模型設計


一、dvc_division表

描述:四級地址表
表結構:
字段名稱
字段類型
是否能夠爲空
描述
id
bigint
主鍵
name
varchar(128)
名稱
code
varchar(32)
編碼
level
int
層級:一、二、三、4
parent_code
varchar(32)
上級地址code
country
varchar(16)
默認CN
language
varchar(16)
默認ZH_CN
status
int
1正常,2廢棄
post_code
varchar(16)
郵編
longititude
varchar(32)
經度
latitude
varchar(32)
維度
version
int
版本號
feature
varchar(1024)
擴展字段
gmt_created
datetime
建立時間
gmt_modified
datetime
修改時間
上面的表結構以一種一維的角度描述了四級地址,可能不太直觀,下面用一個例子來講明四級地址是怎麼組織的:


四級地址第一級:
省份編碼兩位,從1開始到34表明34個省級行政區(23省+4直轄市+5自治區+2特別行政區),以浙江爲例爲8
四級地址第二級:
城市編碼兩位,從01開始遞增,省份+城市構成二級地址,以杭州爲例就是801
四級地址第三級:
區域編碼兩位,從01開始遞增,省份+城市+區域構成三級地址,以杭州西湖區爲例就是80103
四級地址第四級:
街道編碼兩位,從01開始遞增,省份+城市+區域+街道構成四級地址,以浙江省杭州市西湖區古蕩街道爲例就是8010301
上面的每一級地址都經過parent_code關聯上一級地址,所以只要知道任意一級地址,均可以把整個四級地址都查出來。

二、user_address表

描述:用戶地址表
表結構
字段名稱
字段類型
是否能夠爲空
描述
id
bigint
主鍵
user_id
bigint
用戶ID
user_name
varcahr(64)
用戶名稱
shop_id
bigint
店鋪ID
user_type
int
用戶類型:1買家,2賣家
telephone
varchar(16)
手機號
phone
varchar(16)
座機號
country
varchar(16)
國家,默認CN
province
varchar(16)
省份名稱
province_code
varchar(32)
省份code
city
varchar(32)
城市名稱
city_code
varchar(32)
城市code
area
varchar(32)
地區名稱
area_code
varchar(32)
地區code
street
varchar(32)
街道名稱
street_code
varchar(32)
街道code
detail_address
varchar(1024)
詳細地址
address_code
varchar(32)
最小code
is_default
int
是否默認,1默認,2非默認
language
varchar(16)
語言,默認ZH_CN
post_code
varchar(16)
郵編
version
int
版本號
feature
varchar(1024)
擴展字段
gmt_created
datetime
建立時間
gmt_modified
datetime
修改時間
索引:
user_id普通索引


3、四級地址庫高併發設計

四級地址庫的使用場景是查詢很是多,修改和建立幾乎沒有,所以咱們首先想到的是使用緩存。對於緩存,有基於redis的集中式緩存,也有基於JVM的本地緩存,考慮到四級地址庫的使用場景,基於redis的集中式緩存在後期不必定能支撐巨大的查詢量,所以咱們從一開始就選擇基於JVM的本地緩存,下面是對本地緩存的技術選型:

一、基於Guava Cache+定時任務


該策略使用guava cache作本地緩存,因爲guava cache本質上是KV數據,所以針對不一樣的查詢場景,須要構建不一樣的緩存,而後經過elastic-job定時(好比天天凌晨)將數據庫數據刷新到緩存。這種策略編碼實現比較簡單,可是沒法適應複雜場景的查詢,並且隨着查詢場景的增多,內存數據會愈來愈大。

二、基於H2內存數據庫


該策略基於H2內存數據庫+Mybatis實現了複雜查詢場景,同時又保證了性能。可是,因爲H2數據庫的數據是在啓動的時候從文件加載的,運行期沒法變動,所以,每次地址庫更新,都須要更新啓動時的數據文件。

三、最終決策

考慮到四級地址數據一年也更新不了幾回,咱們最終選擇了方案二:基於H2內存數據庫的緩存。咱們把H2數據文件、H2數據庫SQL、Mybatis接口都封裝在了一個client中打包出去,外部系統直接依賴這個client包就能夠得到四級地址庫的能力。當地址庫數據更新,咱們會從新打包client,其餘應用只要升級這個client包就能夠得到最新的四級地址數據。

4、基於經緯度的用戶地址查詢

用戶在下單的時候,須要填寫收貨地址,普通的填寫方式經過四級地址一級一級往下填,用戶體驗比較繁瑣。爲了提高用戶體驗,咱們能夠根據用戶的經緯度直接匹配出四級地址。
咱們使用Redis GEO API進行地址與經緯度的映射,總體架構以下:


咱們首先將用戶地址經緯度映射到四級地址code中,存入redis,前端應用根經緯度從redis獲取四級地址code,而後根據code查詢四級地址詳細信息。因爲數據存儲在redis,爲了防止緩存被逐出或者redis被重啓,天天凌晨使用定時任務刷新redis的數據。
咱們使用redis geo API主要使用兩個命令:
1.GEOADD
命令:GEOADD key longitude latitude member [longitude latitude member ...]
命令描述:將指定的地理空間位置(緯度、經度、名稱)添加到指定的key中。
返回值:添加到sorted set元素的數目,但不包括已更新score的元素。

2.GEORADIUS
命令:GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
命令描述:
以給定的經緯度爲中心, 返回鍵包含的位置元素當中, 與中心的距離不超過給定最大距離的全部位置元素。
範圍可使用如下其中一個單位:
  • m 表示單位爲米。
  • km 表示單位爲公里。
  • mi 表示單位爲英里。
  • ft 表示單位爲英尺。

5、總結

經過上面的介紹,咱們基本介紹完了一個物流地址系統的關鍵技術要點,接下來的一篇文章會把物流詳情和物流服務的能力一併介紹,而後進入咱們的重頭戲:如何構建一個具備良好擴展性的物流產品服務層。

更多文章歡迎訪問 http://www.apexyun.com/前端


聯繫郵箱:public@space-explore.comgit

(未經贊成,請勿轉載)redis

相關文章
相關標籤/搜索