基于中台思想的物流系统设计(三):构建物流地址能力
一、引言
在电商物流领域我们会涉及到地址,其中包括了基础的四级地址和用户填写的地址。四级地址在整个从下单到收货的业务流程中都会用到,因此设计的时候要考虑如何最大限度地提高QPS。用户地址在下单的时候让用户填写或者选择,然后存在交易订单和物流订单上,后续的流程一般不会变,如果用户需要修改地址,直接变更交易订单和物流订单的地址信息即可,因此设计的时候主要考虑满足各种用户地址场景。
二、物流地址数据模型设计
1、dvc_division表
描述:四级地址表
表结构:
字段名称 |
字段类型 |
是否可以为空 |
描述 |
id |
bigint |
否 |
主键 |
name |
varchar(128) |
否 |
名称 |
code |
varchar(32) |
否 |
编码 |
level |
int |
否 |
层级:1、2、3、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关联上一级地址,因此只要知道任意一级地址,都可以把整个四级地址都查出来。
2、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普通索引
三、四级地址库高并发设计
四级地址库的使用场景是查询非常多,修改和创建几乎没有,因此我们首先想到的是使用缓存。对于缓存,有基于redis的集中式缓存,也有基于JVM的本地缓存,考虑到四级地址库的使用场景,基于redis的集中式缓存在后期不一定能支撑巨大的查询量,因此我们从一开始就选择基于JVM的本地缓存,下面是对本地缓存的技术选型:
1、基于Guava Cache+定时任务
该策略使用guava cache做本地缓存,由于guava cache本质上是KV数据,因此针对不同的查询场景,需要构建不同的缓存,然后通过elastic-job定时(比如每天凌晨)将数据库数据刷新到缓存。这种策略编码实现比较简单,但是无法适应复杂场景的查询,而且随着查询场景的增多,内存数据会越来越大。
2、基于H2内存数据库
该策略基于H2内存数据库+Mybatis实现了复杂查询场景,同时又保证了性能。但是,由于H2数据库的数据是在启动的时候从文件加载的,运行期无法变更,因此,每次地址库更新,都需要更新启动时的数据文件。
3、最终决策
考虑到四级地址数据一年也更新不了几次,我们最终选择了方案二:基于H2内存数据库的缓存。我们把H2数据文件、H2数据库SQL、Mybatis接口都封装在了一个client中打包出去,外部系统直接依赖这个client包就可以获得四级地址库的能力。当地址库数据更新,我们会重新打包client,其他应用只要升级这个client包就可以获得最新的四级地址数据。
四、基于经纬度的用户地址查询
用户在下单的时候,需要填写收货地址,普通的填写方式通过四级地址一级一级往下填,用户体验比较繁琐。为了提升用户体验,我们可以根据用户的经纬度直接匹配出四级地址。
我们使用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 表示单位为英尺。
五、总结
通过上面的介绍,我们基本介绍完了一个物流地址系统的关键技术要点,接下来的一篇文章会把物流详情和物流服务的能力一并介绍,然后进入我们的重头戏:如何构建一个具有良好扩展性的物流产品服务层。
更多文章欢迎访问 http://www.apexyun.com/
联系邮箱:public@space-explore.com
(未经同意,请勿转载)
基于中台思想的物流系统设计(三):构建物流地址能力相关推荐
- 基于中台思想的物流系统设计(二):构建物流订单能力
一.引言 物流订单能力作为基础能力,需要设计一套稳定的订单模型,以及一套能够在高并发环境下持续可用的接口.这些接口作为原子接口,供上层业务复用.上层业务无论多么复杂,通过这些原子接口,最终都会收敛到稳 ...
- 基于中台思想的物流系统设计(一)
一.总体设计 在中台架构中,我们往往把一个系统划分为基础能力层和产品服务层.其中,基础能力层聚焦于稳定收敛的业务模型和基础服务本身,不会随着业务和前台产品的调整发生变化,平台产品层则专注于通过流程编排 ...
- 基于中台思想的物流系统设计(四):物流服务与物流详情
一.概述 在物流系统中,中台只负责物流订单的流转,具体的物流履行往往需要对接第三方快递公司.由于第三方快递公司的技术标准不一样,因此我们需要对第三方快递公司的接口进行封装,这里涉及到两大类封装,一个是 ...
- 【电路分享】基于8086投票器积分器系统设计、8086数码管数字钟计时器、8086密码锁可修改仿真、8086可控交通灯系统设计、8086流水灯系统设计、8086三位电压表电压采集仿真
微机原理-基于8086投票器积分器系统设计-protues仿真-361 利用所学8086系统的知识设计一个可以实际使用的八人投票表决器,利用开关按钮作为投票按键,通过8255采集八人的投票信息作为输入 ...
- 基于java的快递物流查询系统_毕业论文-快递管理基于java的物流快递管理系统设计.doc...
毕业论文-快递管理基于java的物流快递管理系统设计 快递管理系统 毕业设计论文 题 目 快递管理系统 姓 名 王敏雪 所 属 系 数学与计算机科学 专 业 计算机科学与技术 班 级 07级计科三班 ...
- 基于Android的手机订餐系统设计与实现(三)
基于Android的手机订餐系统设计与实现(三) 文章目录 基于Android的手机订餐系统设计与实现(三) 一.HomeFragmet中的listItem的点击事件. 1.gain() 2.建立*C ...
- 嵌入式项目实战——基于QT的视频监控系统设计(三)
嵌入式项目实战--基于QT的视频监控系统设计(三) 进入到五一假期第三天,继续我们的项目.本来五一假期还是想好好休息一下的,因为最近学习的状态不太好,刷题都没有思路了,但是身边的同学太卷了,不过我还是 ...
- 【IoT】基于 CC2530 的 ZigBee 物联网系统设计
1.1设计背景 无线传感器网络是目前研究的热门领域,它集成 了多门学科的知识,应用领域广泛,因此深受国际社会 的关注. 在 21 世纪里,无线传感器网络技术是具有 较大影响力技术中的一个热门技术,也是 ...
- 基于python的在线音乐系统设计与实现
摘 要 本音乐系统借助了当前互联网的发展趋势,近几年,随着网络的快速发展,网络已经融入人们的生活中.互联网给人们的生活带来了许多便利,基本上可以达到足不出户就能完成许多事情.互联网的使用基本实现全覆盖 ...
最新文章
- ttl传输中过期的原因_Redis流行的原因
- Hadoop RPC机制的使用
- python定义匿名函数关键字_Python(11):Python函数基础(定义函数、函数参数、匿名函数)...
- html悬停显示图片,JS实现悬停单元格显示图片
- 分布式配置管理平台XXL-CONF
- Anormaly_Detection_with_Keras
- mapxtreme for java_MapXtreme For Java 4.8.2 超菜入门
- pycharm生成linux可执行程序,Pycharm生成可执行文件.exe的实现方法
- 使用Resource Hacker+W32Dasm+OD移除警告窗口
- 七牛云智能日志管理平台的应用与设计
- 【gp数据库】十条实用数据库SQL优化建议
- 腾讯云实验室linux基本操作
- Python GUI制作实例 wxPython使用多线程 防假死含wxFormBuilder的文件及源码
- iOS 手势的使用方法(一)
- 人工智能 --- Python求解线性和非线性规划问题
- 数据库概论之MySQL表的增删改查1
- git仓库的基本使用_码云中国
- unity 创建Txt文件并写入数据
- 从零搭建Linux服务器以及部署Web项目指南
- 通过 MarqueeFactory 来提供各种样式的跑马灯 View, 支持自定义跑马灯 ItemView
热门文章
- debian重启ssh服务_秒变万能家庭服务器!斐讯N1 armbian安装指南
- MySQL系列【一】:索引底层数据结构和优化
- Libevent 学习一:Libevent 源码编译
- 无Mac机IOS开发环境搭建手记
- 小屏幕Android机,Palm:3.3英寸小屏安卓机来了
- 集群(Trunking)调度通信系统
- Maven 中央仓库地址大全
- 魔兽怀旧服怎么找不到服务器,魔兽世界怀旧服服务器连不上怎么办
- Python+Vue计算机毕业设计包头市大学生家教信息中介平台aizx2(源码+程序+LW+部署)
- 硕士论文答辩PPT的要求