基于Redis实现邮费存储
2017-07-19 10:08
253 查看
基于Redis实现邮费存储
需求
首先说明一下情景:有多家供应商在某一平台上出售自己的商品,平台要根据顾客的收货地址,按照供应商是否有针对该地址的特殊计费方式,计算物流信息。
因为每家供应商可以和多家物流公司有合作,假设各家物流公司的计费方式是:一定重量内,按照统一价格收费,超出后,当每超出额定数额,按照该数额计算。而且还可以针对特殊省份,比如港澳台、西藏等设置特殊的计费方式。
其中存在多种一对多的情况:
有多家供应商
有多家物流公司
一个供应商可以和多家快递公司合作
一个供应商可以针对一个家快递公司设置多个特殊省级计费方式(这里只让供应商设置到省级,可以到更具体的区域,但是这里暂时只实现省级)
其次,要根据顾客的收货地址和供应商下所拥有的全部物流公司和是否有针对该收货地址的特殊设置来计算邮费价格。
MySQL存储结构
如果要采用MySQL来存储这种结构的话,那么就需要以下几张表
快递公司表
字段名 | 字段说明 |
---|---|
shipping_id | 主键 |
shipping_name | 快递公司名称 |
shipping_code | 快递公司代码 |
字段名 | 字段说明 |
---|---|
id | 主键 |
supplier_id | 供应商id |
shipping_id | 物流公司id |
shipping_kinds_id | 配置id |
province | 该配置下的省份id |
winthinWeight | 首重 |
winthinCost | 首重内统一价格 |
beyondPerGram | 超出一定重量 |
beyondPerGramCost | 超出后重量价格 |
但是这样的话,供应商与物流公司表的记录就会特别多,假设供应商有x位,有y家物流公司,每家公司设置z个配置,加上一个默认设置,就是如果供应商不设置特殊的省份计算方式,则按照该设置进行计算。那么总共有多少条记录数:
x∗y∗(z+1)
拿一个具体的值来说,我们可能拥有的供应商有500位,有5家快递公司,每家快递公司推出4款针对港澳台、西藏等的特殊地区的收费套餐,那么记录数有多少
(5∗500∗(4+1))=12500
而且查找时,你需要根据
$supplier_id,供应商id,
$province,收货商的收货地址,查找该供应商下是否有关于该省份的特殊设置。而且这里为了减少一个物流配置中有多个省份的一对多的情况,还把省级信息保存成以
,(逗号)隔开的数组,这样当我们搜索时,只能根据
$supplier_id,查找出全部数据,再来遍历,这样的效率是比较底的。
Redis结构
关于Redis的基础知识可以参考我的这一篇博客这里不一定要使用Redis,只是我现在在跟的项目中有使用Redis,于是大哥就说用Redis试试,结果是试虽然试出来了,但是结构比较复杂,没办法,毕竟关联对象比较多:
供应商
物流公司
物流配置
在该配置下的省份
其上每一个关系都是一对多。这时可能第一反应是使用哈希结构来存,比如使用哈希表模拟表之间的关联:
// 模拟供应商与快递公司的关联表 $supplier_id:{ $shipping_id1:$next_hash_key, $shipping_id2:$next_hash_key2 ... } // 模拟该快递公司下各物流配置的情况 $next_hash_key:{ $shipping_kinds_id1:json("首重,超出后等配置信息"), $shipping_kinds_id2:json(""), ... }
其中以
$supplier_id为
Key,以
$shipping_id为字段,以另一张存储快递公司多种配置信息的
key。这样有问题吗?基本没有,但是回到最基础的问题上来,这样可以很方便的根据供应商
$supplier_id和省级
$province_id来查找出配置信息吗?
还是很麻烦,因为只是换了个方式去遍历数组而已。这个时候我突然想到一种不是很邪门,但是应该可行的方案:
为什么我不根据已有数据,重新构建他们,方便我的查询呢?
有了这个思路之后,我就想在上面数据的结构上,构建以下格式的数据:
$supplier_id:{ $province_id:{ json( {$shipping_id=>{'首重等配置信息'}} ) } }
这里,我把
$province_id作为字段进行存储,这样查询时就可以使用
hget key field,即
hget $supplier_id $shipping_id的结构进行查询,如果能够查到数据,表名该供应商有关于该省份的特殊设置,如果查不到,则表示没有特殊设置,那么没有办法,只能遍历各家快递的默认设置,然后计算最低价格。但是我们也可以把默认设置保存进上面供查询的数据中,于是数据就变成了这样:
$supplier_id:{ $province_id:{ json({$shipping_id=>{'首重等配置信息'}}) }, 'defaults':{ json({$shipping_id=>{'首重等配置信息'}}) } }
这样的设置其实不适合经常要修改数据的方案,因为你一旦更新数据就要更新给前台查看的数据,就是上面的数据格式。当初这样设想是假设物流配置不会经常更新,而且前台查询比较方便。
到此为止,基本的思路都完成了,在这里总结一下数据结构:
存储数据
# 集合,存储该供应商下全部的物流公司id "SupplierID".$supplier_id:{$shipping_id1,$shipping_id2} # 存储该供应商下的物流配置 "SP".$supplier_id."SP".$shipping_id:{ $shipping_kinds_id:json("各种配置信息") }
上面之所以只用集合,是因为我们可以自己创建关于供应商与物流的
key,这样就不用多存储多一个值了。下面是我为了优化而多添加的内容:
# 集合,存储该供应商已经设置了特殊的省份 "SP".$supplier_id."SP".$shipping_id."PRO":{ $province_id1,$province_id2,... }
这样做的目的是为了优化用户的选择,比如当供应商在设置韵达快递的物流配置时,对宁波市,只能设置一个配置信息,否则一家快递公司对同一个地区有不同设置,这样无疑是多余的,这样的辅助功能不一定要,但是有的话,必定是极好的(甄嬛附体!!!我是甄嬛转的脑残粉。。。)
提供功能
有了上面的数据结构,那么可以给供应商开通哪些功能呢?新建物流公司=>
管理员
修改物流公司信息=>
管理员
(删除物流公司,这个我个人并不赞成给,可以修改,但是删除的话,不能保证是否有别的供应商使用该物流)=>
管理员
配置物流公司计费套餐=>
供应商
删除该计费套餐(这里可以删除)=>
供应商
关闭物流公司配置=>
供应商
其中各个功能与该功能中的使用者也列出来了,接着就是编写具体的代码了,这个我已经在自己的
github上新建了一个仓库,等到代码完善之后就可以分享出来了。
相关文章推荐
- 分布式锁实现方案1、基于Redis的SETNX操作实现的分布式锁
- 分布式Session:基于Spring-Session 和 Redis实现
- 基于Redis实现分布式锁
- 基于redis实现的点赞功能设计思路详解
- 基于redis(key分段,避免一个key过大) 和db实现的 布隆过滤器(解决hash碰撞问题)
- 服务注册发现consul之四: 分布式锁之四:基于Consul的KV存储和分布式信号量实现分布式锁
- 基于Redis实现分布式应用限流
- 消息列队 php 基于redis 实现
- 基于redis的分布式锁的实现
- 基于AVI的网络视频监控存储系统的实现方法
- [原创]实现基于文件存储的Session类
- SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例(转)
- 基于连续存储空间的链表实现
- 基于 Redis 数据累计的实现
- 哈希存储整理(基于共享内存的实现)二
- golang sortedset 实现(基于redis skiplist)
- 基于redis(key分段,避免一个key过大) 和db实现的 布隆过滤器(解决hash碰撞问题)
- 基于Redis实现分布式锁
- 基于redis的分布式锁实现
- 基于redis实现的扣减库存