首先,这是个人在项目中所设计的一种。大家在使用的过程中还是应该结合自己项目的实际情况来区别对待。
1、对订单进行分库、分表的处理
原因:其实,原因很简单。如果你的订单在每秒达到10万乃至更高,单是一个订单库是绝对承载不了这么大的数据冲击的。所以对此我们要对其进行一个分库、分表的处理。
实施:在实施过程中,我们所依据的原则便是根据用户的id来对其进行一个分库处理。(因为每个订单都是由用户进行下单的,所以每个订单信息中也必然有关于用户的信息,在用户进行订单查询的时候同样需要通过用户的id,所以在 这里我们就选择了以用户的id来对订单库进行划分)。
规则:我们采用的是“二叉树”的拆分方式来拆分的。(2,、4、8、16……因为对于电商项目来说,我们很可能将要面对更大的数据量,这也就意味着。在项目的后期我们需要对数据库进行扩容处理。这里我们选择“二叉树”的方式,,那么在以后扩容的时候只需要DBA来进行表级数据的扩容就可以了,不需要我们再写一些脚本进行行级数据的扩容,这样是很麻烦的啊!)
运算方式:(uid/10)%8 + 1 = 对应的库; uid%10 = 对应的表 这里的库是我们所划分的第几个库,表则是所对应库中的具体那张表。uid便是我们的用户id。刚开始的时候我们选择的仅仅是分库处理,不过在压测的环节我们发现数据表之间的关联性很高所以这里我们又对规划好的8个库进行了0——9,10张表的分表处理,即每个库中都对应着10张表。
扩容:目前,项目中所应用的是8个库,在实际应用中我们可能面临着数据库扩容的处理。所以,在这里我们选择的便是将数据库前期定义为128个库,这样一来便为今后数据库的扩容准备了条件。算法的规则依然是按照上面的规则来的。
订单:对于订单而言我们不仅仅是将订单的数据放到所对应的数据库中而已,我们还需要对其数据进行一个查询。那么,这里我们先来讲一下订单的相关内容。相信大家应该都知道订单在我们的商品属性中是具有唯一性的。一般在我们的项目中所使用到的是UUID,但是我们这里所使用到的并不是他。因为他含有相应的字母等东西在进行解析或增加的时候会降低程序的一个效率。所以在这里我们所使用的是另一种方式。 即:时间戳 + 每毫秒订单号的一个自增 + 机器号,从而得出所对应的唯一订单id,】而在查询的时候我们需要知道其所对应的库和表,所以在订单id的前面我们还添加了所对应的库表信息。库表信息所拼接的规则也是按照uid来计算的。
2、数据的分级处理
仅仅只是对订单进行一个分库处理也是不够的,我们需要尽可能的降低数据库的一个压力。所以在这里我们根据信息重要程度的不同对数据进行了一个分级存储。首先便是对于“支付流水”,涉及到money的问题都是敏感问题容不得出错,所以关于这部分信息我们直接使他和数据库进行关联。而所对应的用户信息,很多都是只读不写的操作,所以在这里我们便将这部分数据放到了redis的缓存中。最后便是所返回的订单的一个信息,基本上也是不需要进行大的改动的,所以我们就将这部分数据信息放到了本地。。那么,这里便涉及到了一个很严重的问题。数据信息之间不统一,那么对于这个问题我们是如何解决的呢?这里我们使用到了“消息队列”的方式,当然仅仅是这样也是不够的。我们还写了一个高可用的时间类,对数据同步进行定时的一个同步。
3、大数据的过滤
我们在做一款东西的时候,便涉及到一种问题。在我们做之前便需要对产品进行一个整体的规划。电商所遇到的便是数据量的一个问题当然不排除恶性攻击。然而我们目前所能承载的数据量是10万左右,在压力测试的时候所能达到的峰值是15万。那么,当我们遇到100万或者更高的数据量时我们应该怎么做。在搭建项目的时候我们是进行Nginx负载的。而Nginx中有“粗管道”和“细管道”之分。这里我们便用到了。我们在外围所进行的数据量的一个拦截是100万,在内围数据进行了10万的数据量拦截。并在Nginx后的数据进行了集群的一个负载。
大致我们是通过这样的一种方式来进行的。当然在这里仅仅是为大家提供一种思路,更深入的问题还需要根据大家不同的需求来进行不同方式的解决。相信大家能够有更好的设计方案。谢谢大家。