从分库分表后遗症,总结数据库表拆分策略
我们假设上面是一个订单列表,orderID订单号大家就不要在意顺序性了。因为Sharding之后所有的orderID都会由发号器统一发放,多个集群多个消费者同时获取,但是创建订单的速度是不一样的,所以顺序性已经不存在了。 上面的两个Sharding node基本上订单号是交叉的,如果按照时间排序node 1和node 2是要交替获取数据。 比如我们的查询条件和分页参数:
获取的结果集为:
前面4条记录来自node 1后面1条数据来自node 2 ,整个排序集合为:
按照这样一直翻页下去每翻页一次就需要在node 1 、node 2多获取5条数据。这里我们可以通过修改查询条件来让整个翻页变为重新查询。
因为我们可以确定在‘2018-01-11 10:10:13’时间之前所有的数据都已经查询过,但是为什么时间不是从‘2018-01-21 10:10:10’开始,因为我们要考虑并发情况,在1s内会有多个订单进来。 这种方式是实现最简单,不需要借助外部的计算来支撑。这种方式有一个问题就是要想重新计算分页的时候不丢失数据就需要保留原来一条数据,这样才能知道开始的时间在哪里,这样就会在下次的分页中看到这条时间。但是从真实的深分页场景来看也可以忽略,因为很少有人会一页一页一直到翻到500页,而是直接跳到最后几页,这个时候就不存在那个问题。 如果非要精准控制这个偏差就需要记住区间,或者用其他方式来实现了,比如全量查询表、Sharding索引表、最大下单tps值之类的,用来辅助计算。(可以利用数据同步中间件建立单表多级索引、多表多维度索引来辅助计算。我们使用到的数据同步中间件有datax、yugong、otter、canal可以解决全量、增量同步问题)。 三、分表策略 分表有多种方式,mod、rang、preSharding、自定义路由,每种方式都有一定的侧重。 我们主要使用mod + preSharding的方式,这种方式带来的最大的一个问题就是后期的节点变动数据迁移问题,可以通过参考一致性Hash算法的虚拟节点来解决。 数据表拆分和Cache Sharding有一些区别,cache能接受cache miss ,通过被动缓存的方式可以维护起cache数据。但是数据库不存在select miss这种场景。 在Cache Sharding场景下一致性Hash可以用来消除减少、增加Sharding node时相邻分片压力问题。但是数据库一旦出现数据迁移,一定是不能接受数据查询不出来的。所以我们为了将来数据的平滑迁移,做了一个虚拟节点 + 真实节点mapping 。
为了减少将来迁移数据时rehash的成本和延迟的开销,将Hash后的值保存在表里,将来迁移直接查询出来快速导入。 Hash片2的次方问题 (编辑:威海站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |