这几天设计讨论的一点心得

这几天和同事讨论新项目、系统的设计方案。理越辩越明,有一些以前模模糊糊的想法、概念,都随着讨论,有时甚至是争论而变得清晰明确。

服务接口的幂等性。

以前做服务接口,都没考虑过这个问题。这次静下来想了想,觉得服务接口必须具备幂等性才对。

幂等性就是说,在没有其它操作的情况下,对同一个服务接口无论调用多少次,系统状态以及返回结果都应当是一样的。

如果不是这样,前后脚两个操作,一个告诉我说OK了,另一个告诉我说出异常了。这算什么鬼=。=

就一般的增删改查来说,删改查基本上是很容易支持幂等性,甚至天生幂等的。

但是新增,由于语义上每次都要追加一条数据,那么多次操作当然会多次增加数据咯。

让新增操作变成幂等性操作,需要有重复校验。页面提交上可以带token,但是服务接口呢?

恐怕只好做唯一数据校验吧……这个校验又可能涉及到事务和并发的处理……

于是麻烦了,算了,直接抛出异常告诉服务调用者“数据重复”吧!

这是服务还是别的什么鬼=。=

我这次做的一个接口,向着“幂等的新增接口”走了一步,保持其对外的语义是:你给我一笔数据,我返回一个唯一标识;相同的数据,返回相同的标识。

自我感觉良好o( ̄▽ ̄)ゞ

数据库字段设计

在与同事讨论系统中一个数据库设计时,谈到了一个数据库字段设计的选择思路:

数据库是严格遵循范式以获得sql的各种便利,还是存复杂结构(数组,甚至json)以获取更强的灵活性和扩展性?

 

设计场景

系统需要为实体A、实体B和B1做相关配置。其中:

  • A:B是1:n的配置关系
  • A:B1是1:1的配置关系
  • B和B1是同类型的数据

未来,可能出现:

  • A:D配置
  • A:E配置 ……

争论的焦点

主要是以下两种方案。

遵循范式的方案

表字段设计为“商户id”、“银行通道id”这两个字段,每一条商户-银行通道的配置存一行,例如(示例;其它关联表或基础配置表没有写出来):

AB
123B1
123B2
123B3
456B2
456B4

存复杂数据结构的方案

表字段设计仍然是两个字段,但每一条数据中的“银行通道id”字段,存数组(甚至讨论过存json字符串的方案),例如:

AB
123B1,B2,B3
456B2,B3
789{"C":"B1","B":B3","B5"}

两种方案的优缺点

遵循范式的方案可以最大程度的支持sql。例如,如果运营需要统计有多少A配置了指定的B(这是我在做另一个类似的需求时实际遇到过的,算是前车之鉴),则这种方案可以很便捷的得到结果。

但是,为了遵循范式,数据量(行数,并非实际的存储空间)会变得很大。最糟糕的情况下,可能出现50w「A的数量」*(19「B的数量」+1「C的数量」)=1千万行数据。从这样大的数据量中查出20行数据(而且还要进行关联查询),查询效率堪忧。

另外,遵循范式使得库表设计严格的规定的数据结构及实体间关系。也就是说,这个表只支持A到B/C的映射配置。如果后续需求中的D或者E不是以这种结构、关系进行配置的,那么就只能用新的表结构来扩展了。  

存复杂数据结构的方案的优缺点基本上恰好相反。它对sql的支持比较差,数据需要在代码中进行额外的处理。尽管实际占用的存储空间可能会更大一些,但是数据行数会大量减少(使用json的话,最糟糕情况就是50w行),查询效率会好一些。而且,只要数据不超长,json可以兼容各种各样的数据结构,非常的灵 活便捷。

 

我们的讨论结果

合天弘运文武睿哲恭俭宽裕孝敬诚信功德大成仁之交哥二话没说,使用了遵循范式的方案。

我的理解是这样

  1. 有前车之鉴,B的配置数据可能要用作sql中的where字句条件。如果用复杂数据结构,这一点很难支持。
  2. 数据行数的隐患可以配合另一种设计方案解决。
  3. 新的数据结构可以通过扩展新的表来实现。

这样一来,复杂数据结构的优势缩小,而劣势就被放大了。

©著作权归作者所有:来自51CTO博客作者winters1224的原创作品,请联系作者获取转载授权,否则将追究法律责任 这几天设计讨论的一点心得 https://blog.51cto.com/winters1224/1613832