游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

电商平台通用取货码设计

  一、背景
  随着O2O线上线下业务的不断扩展,电商平台也在逐步完善交易侧相关的产品功能。在最近的需求版本中,业务方为进一步提升用户的使用体验,规划了取货码生成及订单核销相关逻辑,目的是让线上的用户在付完款之后能够到店取货或者安排导购派送。
  日常生活中,我们对取货码、核销这类功能使用的经历大部分都来自:看电影前取票、吃饭后出示券码、快递柜取包裹等等,它们都有一些类似的特点,比如:取货码长度相对较短,比起动辄十几二十位订单号,几位的数字码更方便记忆和输入;除了数字取货码,还提供二维码,方便终端进行扫描并核销。
  取货码使用起很简单,然而像冰山一样,隐藏在简单外表下面却需要严谨的设计和细致的逻辑,可以说麻雀虽小五脏俱全。本文介绍的设计也比较有趣,而且按此思路可以实现市面上大多数核销类券码的生成,同时也能满足业务的SaaS化,算是一个相对通用的能力,在此把整个设计分享给大家。
  二、简单系统的单表业务
  如果业务的体量不大,店铺流量比较小,未形成平台的规模,比如给个体经营者使用的系统。那么取货码或券码的实现就比较简单,跟订单共享一张大横表或者使用扩展表跟订单进行关联就行了,这个阶段也无需做过度设计。
  表的设计如下图:
  不过需要注意的是一般订单号都是比较长的,通常都在十几二十位(当然也有比较短的订单号,如果订单号比较短,取货码也可采用订单号)我们假设订单号18位,取货码8位,即订单号的取值范围远大于取货码,那么在订单号的生命周期内,取货码是有很大几率存在重复的。解决起来相对简单,我们只需要保证在任意条件下,未核销状态的数字码不重复即可,也即已核销的数字码可以回收利用。
  那么取货码的生成逻辑就很清晰了,下面用伪代码模拟真实的实现逻辑:
  伪代码实现for(;;){step1获取随机码:Stringcodethis。getRandomCode();step2执行SQL:SELECTCOUNT(1)FROMordermainWHEREcode{code}ANDwriteoffstatus0;step3判断是否可以插入:if(count0){continue;}step4执行数据写入:UPDATEordermainSETcode{code},qrcode{qrCode},writeoffstatus0WHEREorderno{orderNo}}
  注意:这里step2和step4不是原子操作,存在并发问题,实际应用中最好使用分布式锁,把操作锁住。
  三、复杂平台的分库分表业务
  通过简单的单表设计,我们能管窥一斑,了解取货码大致的实现逻辑。不过我们在把简单方案往大型项目上进行落地的时候,就需要考虑很多方面,设计也需要更精巧。SaaS化的电商平台会比简单的单表业务复杂很多,重点体现在:SaaS产品涉及的店铺很多且订单量大,需要设计大容量存储,所以订单表基本使用分库分表,显然作为订单附属的取货码表也得使用相同的策略;B端和C端用户的体验非常重要,服务端接口的设计需要充分考虑鲁棒性,完善最基本的重试及容错能力;不同业务方对于取货码的要求可能不太一样,取货码的设计需要具有通用性以及个性化的配置属性。
  3。1详细设计
  取货码表的设计推荐使用和订单一致的分库分表策略,好处是:和订单一样,支撑海量订单行的存储;方便利用同样的分库分表因子进行查询(例如:openid、memberid)。
  在考虑落地实现上,我们遇到了第一个讨论的点,那就是取货码是做到门店唯一还是全局唯一?
  3。2门店唯一方案
  刚开始考虑使用类似饭馆取餐码类似的逻辑,保证取货码在各自门店保持唯一就行了。类似如下图交互,图中用户A和用户B持有相同的取货码,用户A、B分别去他们对应的店铺完成核销,整个交易过程就结束了。但是这得保证用户A和B能正确地在各自订单归属的店铺完成核销,显然这个方案是带有风险的!
  下图所示的这种情况下,用户A、B也能正常核销,不过串单了,原本属于用户A的订单被用户B核销了。这种问题出现的本质原因在于纯粹的数字码无法带有用户的标识,虽然可以在核销前做人为的核验身份来避免,但依然属于高风险的系统设计,所以门店唯一方案不可取!
  3。3全局唯一方案
  全局唯一方案风险小,但实现难度稍高一点。核心问题在于如何判定随机生成的取货码是全局唯一的,当然如果系统本身依赖ES这类存储介质,可以在插入前先查询ES,不过查询和写入ES对于实时性接口来说稍微有点重,没有直接查库表来得直接。假设某业务方分成了4个库4张表,总计16表,取货码的长度确定为8位,那如何在多库多表的Mysql中查询并保证全局唯一呢?遍历表的方式肯定不可取!
  为解决上述的疑问,我们在设计的时候可以在取货码的编排上做点文章,如下步骤做具体详解:
  步骤:可以将8位的取货码分成两个区域,随机码区域库表位置,下图示例:
  步骤:随机码区域暂不介绍,我们来看下2位库表如何映射到4库4表组成的16张表中。
  这里也有两套方案:
  【方案一】可以选择2位库表的首位作为库编号,末位作为表编号。好处是映射较为简单,但是容量不够大,如果分的库或表9,扩展就会有点麻烦。如下图,我们把末尾12逻辑映射到了1库的编号为2的表;
  【方案二】将4库4表二维结构转成一维,以0为初始值进行递增,(0库,0表)00,(0库,1表)01。。。,(3库,3表)15。好处是容量变大了,最大支持99张表,不受库或表单一条件的限制,缺点就是映射逻辑写起来麻烦点,不过这不是问题。
  取货码经过简单编排,我们完成了取货码的到库表的映射逻辑,解决了取货码存取的问题。其实仔细想想,关于全局唯一的问题其实也解决掉了,我们只要保证前6位随机码在单表里保证唯一即可,理论上支持单表在未核销状态下范围为:000000999999条记录,容量是足够的。关键我们把多库多表的查询就简化成了只跑一个SQL,效率大大提升。
  3。4方案落地遇到的问题
  既然本篇是介绍SaaS化的完整方案,在落地的时候或多或少会遇到一些问题,这边介绍三个实际遇到的典型问题,并给出一些解决方案:
  【问题一】使用Math。random()生成的6位随机码和表里的重复了,如何处理?
  【解决】其实重复的情况有两种:可能是表里已经存在数字相同未核销的取货码;另外一种情况就是别的事务在正在操作,正好有个分布式事务锁住了一样的数字码(概率很低,但是是有可能的)。
  这两种情况的出现就需要我们进行优雅地重试了!大致思路如下伪代码:step1根据分库分表因子获取库表编号,userCode用户编号、tenantId租户编号StringsuffixgetCodeSuffix(userCode,tenantId);step2批量获取6位随机码for(inti1;i5;i){批量获取随机数。每次重试,取2的指数级量进行过滤,相比暴力执行for循环,这种方式能减少和DB的交互ListStringtempCodesgetRandomCodes(2i);过滤掉分布式锁filterDistributeLock(tempCodes);过滤掉数据库存在的随机码filterExistsCodes(tempCodes);returntempCodes;}step3处理随机码,随机码入库for(Stringcode:codes){加锁,判断加锁是否成功。推荐使用Redis分布式锁booleanhasLockdisLocked(code);try{执行入库insert(object);}finally{解锁}}step4执行后置二维码图片等逻辑
  【注意】推荐使用指数级重试的方式(2i),逐次递增random的数量,减少和DB的交互;建议数字码生成完毕后加锁并执行INSERT,生成图片地址等耗时严重的动作可以后置UPDATE上去。
  【问题二】项目中使用了分库分表的组件(比如:ShardingSphereJDBC),怎么动态修改数据源?也就是同时支持分库分表因子(比如:memberid、openid等)以及根据取货码计算的库表动态查询。
  【解决】我们以ShardingSphereJDBC作为为案例来给出一些配置及伪代码,具体可以参考:《强制路由::ShardingSphere》,其他开源的分库分表组件或者自研产品不做赘述,可以自己手动写个插件,别怕,即使再难,也要相信有光!
  配置及伪代码ShardingSphereJDBC依赖的配置文件jdbcsharding。yaml。。。shardingRule:tables:。。。取货码表ordercode:actualDataNodes:DS00{0。。3}。orderpickup0{0。。3}配置库的计算逻辑databaseStrategy:hint:algorithmClassName:com。xxx。xxxxx。xxx。service。impl。DbHintShardingAlgorithm配偶之表的计算逻辑tableStrategy:hint:algorithmClassName:com。xxx。xxxxx。xxx。service。impl。DbHintShardingAlgorithm。。。java代码try(HintManagerhintManagerHintManager。getInstance()){hintManager。addDatabaseShardingValue(ordercode取货码表,DbHintShardingAlgorithm。calDbShardingValue(tenantId,code));hintManager。addTableShardingValue(ordercode取货码表,DbHintShardingAlgorithm。calTabShardingValue(tenantId,code));ObjectxxxxxxMapper。selectOne(queryDTO);}
  【注意】这里介绍一种编程式的解决方案,好处是配置简单、比较灵活,缺点就是代码稍微多一点。其实ShardingSphere还支持注解的方式,可以自己研究下;第一条说了比较灵活,体现在自己实现的DbHintShardingAlgorithm。calDbShardingValue(tenantId,code)方法上,这个方法可以自己定义,所以我们的入参可以是通用的分库分表因子,也可以是自定义的取货码的库表位置字段,非常灵活。
  【问题三】如何做到更强的扩展性,适用SaaS平台以及不同的业务场景?
  【解决】细心的小伙伴应该注意到了tenantId这个字段,这是个租户的编码,在实际编码会进行透传。我们可以利用这个字段针对不同的租户(或叫业务方)来做不同的配置,比如:取货码的长度、取货码编排的方式、取货码映射库表位置的策略等等做成可配,只要把主干逻辑进一步抽象,并使用策略模式进行个性化编码。
  四、总结
  实现取货码逻辑的时候,发现网上券码这块的方案、技术文章比较少,当时萌生了写篇文章抛砖引玉做个分享的想法。事实上,我相信大多数公司可能或多或少也是这么做的,哪怕采取了别的方案也能殊途同归。本篇文章整体只是介绍了一个思路,而这个思路类似一个简化版的订单分库分表,但这就是神奇所在,事实上我们还可以将一些常用的技术方案落地到不同的应用场景,大胆地做一些尝试,多走一些未曾设想过的道路!

中国哪里的兔子最好吃?俗话说得好:兔兔那么可爱,当然要多加辣!对于从小就浸润在美食文化中的国人而言,无论什么节日,元旦或元宵、端午或中秋,吃都是绕不过的话题。到了兔年,当然就要吃兔了不仅……陈小春的尴尬折射多少演员的无奈时代抛弃你时,连招呼都不会打不知道什么时候网大市场成了烂片聚集地,不少曾叱咤风云的一线明星如今竟然纷纷沦到全网吐槽的地步。其中以阿娇两部口碑翻车的网大为代表,先是在《封神:妲己》中扭动水桶腰强行演狐……想要维护心血管健康?快来测测你的生命8要素能拿多少分?2010年,美国心脏协会(AHA)提出了促进心血管健康的简单生活7条,研究表明,遵循简单生活7条,能终身降低患冠心病等心血管疾病的风险。今年,美国心脏协会又在简单生活7条……2020经典的网络推广素材励志、【一句鼓励自己的话简单】身体健康与否,可以决定一个人勇气与自信的有无,而勇气与自信,又是成就任何事业必备的条件。满的成功,依赖你健全的精神;而健全的精神,依赖你健康的身体。……窒息!国乒男队4人扎堆上半区,张本上上签,周启豪突围需奇迹11月22日,备受关注的休斯敦世锦赛抽签结果出炉,复制了上届一幕,国乒男队四人被抽到上半区,让人哭笑不得,怕你认为窒息。根据规则,世界排名第一的樊振东直接入上半区,随后的……让你安心玩转美国,美国旅游保险购买有妙招不羁的纽约、威严的华盛顿、热情的夏威夷、疯狂的拉斯维加斯美国吸引了无数游客。玩转美国,行程固然美好,但脚下的风险也不容忽视。不少人都计划在出发前购买份适合的保险,您需要结……铁了心重回中国市场,国际巨头正式官宣,华为又要被趁虚而入?虽然2022年刚开始,但是手机行业的竞争却并没有一丝降温。小米12系列的旗开得胜加上一加、IQOO等品牌的强势出击,显然从年初就能看出今年市场的激烈程度。而另一方面,在国产手机……比利时进八强!美国造超级惨案,韩国溃败,女篮世界杯积分榜更新北京时间9月26日,女篮世界杯小组赛第四轮的比赛全面展开,A组率先结束了两场比赛的较量,其中比利时女篮8555击败了波黑女篮,美国女篮14569狂胜韩国女篮,目前在最新的积分榜……世乒赛张本智和大获全胜!日本30横扫巴西,世界第5雨果被爆冷北京时间10月5日下午,成都世乒赛16强赛上演了一场焦点对决,国乒劲敌日本队登场,在男团项目中迎战西半球第一劲旅巴西队。双方各有一位外协会超一流的运动员,分别是世界排名第4的张……记者女足世界杯奖金增至1。1亿美元中国女足上届拿到100万美直播吧3月18日讯据记者马德兴报道,今年女足世界杯的奖金较上届翻番近4倍,如果中国女足有着不俗的表现,获得的奖金也有望大幅度提升。第73届国际足联全体代表大会3月16日在……最难熬的时刻,是低谷,熬过,就能收获幸福人的一生,不顺心事,十有八九。人生道路,诸事难称心;日常生活,随处皆艰辛。每一个人,很有可能都是会踏过一段煎熬的生活。处于低谷期时,大家孤独、崩溃,期待有一两……M416都自叹不如?步枪刺客重获新生,AUG能否再度封神?新版本【科学之轮】带着众多新玩法正式上线后,鸡仔发现特种兵们都沉迷在波波车、蜜獾突击步枪的快乐中,却忽略了新版本的一大重要改动:AUG平衡性调整。今天鸡仔就给大家重新介绍一下这……
男子肺结节一年后被确诊肺癌,肺结节等于肺癌?李某,现年66岁,是小学的一名退休教师,平时不抽烟,不喝酒,饮食清淡,注意养生。一年前因为咳嗽在某三甲医院做肺部ct时,发现肺部有个孤立的肺结节,当时ct显示,肺结节极小,直径……可乐鸡翅好吃,在家做一盘,小孩子都吃不够可乐没喝完,怕浪费,周末在家就做了一份可乐鸡翅,没想到小孩子一个人就把他吃完了。可乐鸡翅味道鲜美,鸡翅嫩滑,小孩子最爱,吃完一个接一个。我们今天就看看,这道可乐鸡翅……被称为沙漠面包的椰枣,香甜软糯,止咳润肺,你尝过吗?椰枣大家可能不太熟悉,又名波斯枣、番枣,是枣椰树的果实,《本草纲目》称无漏子。其实它在中东和印度河流域都是一种很常见的食物。过去在中东地区,椰枣是可以当作主食的,号称沙漠面包。……关于老鼠的乌托邦实验,预言了人类的未来命运?上个世纪60年代一个真实的黑暗实验向我们预示了,当物质极度繁盛之后,人类可能会自己走向衰亡。1968年7月,动物行为学家约翰卡尔宏将四只老鼠放入自己建造的老鼠乌托邦之中,并将这……辽宁锦州央地合作对接会促44个项目签约总投资612亿元锦州市央地合作对接会议现场。锦州市委宣传部供图中新网锦州3月23日电(记者王景巍)3月23日,在辽宁省锦州市召开的央地合作对接会上,央地双方聚焦央锦融合发展共赢振兴突破这……虾仁的最好的吃法是什么?要做出最好吃的虾仁,在选材上很有讲究。新鲜活剥的虾仁,口感是最为爽滑弹性的。在剥虾的时候,顺手把虾线挑了,虾线是有点苦味的,不挑掉的话,会妨碍虾肉本身的鲜甜。……目前为止发现的最大星球大犬座VY恒星大犬座VY是人类目前已知的最大星体,直径达30亿公里,体积接近太阳的100亿倍,是地球的1。6万亿倍。地球和木星对比太阳半径约等于十个木星大犬座VY是一颗位于大……为了境外游重启,我已经等了三年!环球旅行摄影师明年三月带团去对于上海市民来说,旅行已经成为一种休闲文化。各位市民朋友,侬有多久没有出国(境)白相了?侬还记得之前一次去的旅行目的地是哪里吗?政策放宽利好境外游12月26日晚,国……优秀的孩子都会有明显的特点高情商的孩子,他们都很谦虚,即便自己很优秀,也不愿表现出来。生活中,总是喜欢隐藏锋芒,然后去夸奖别人;孩子各方面的能力也很优秀,做事稳重,并且拥有很好的自律能力。重点是,他们很……状元太水,外援太独,土豪却是真土豪状元太水,外援太独,土豪却是真土豪不出意料,上海大比分输给了浙江。雄心勃勃的上海土豪受到了当头一棒,要知道,上海的意图岂止是小小浙江。收购国内外一系列大牌援军,意在问鼎总……秋天进补,吃鸡鸭不如大骨,才9块一斤,加水一焖,口口都是肉秋意盎然,胃口大开,美美是个喜欢吃肉的人,这气温一降,我就特别馋肉,对于喜欢吃肉的人来说,真的想要吃肉的时候,各种的小炒肉是不过瘾的,大口大口的吃肉才解馋呢!最近真的迷上……论口感,山西汾酒贵州茅台,哪种好喝?当然是汾酒啦,茅台只是近些年被炒上了天罢了汾酒醇〔赞〕〔吃瓜群众〕茅台是用来喝的吗?比碳黑〔吃瓜群众〕汾酒是清香型的味道酒的代表,汾酒的口感特点是清香纯正、诸味协调……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网