长文多图:一文讲清楚应对单数据表海量数据的六种策略( 四 )


上述方法优点是对范围查询比较友好 , 例如我们需要统计第一季度的相关数据 , 查询条件直接输入时间范围即可 。




但是这个方案问题是容易产生热点数据 。例如双11当天下单量特别大 , 就会导致11月这张表数据量特别大从而造成访问压力 。


5.2.2 查表分片查表法是根据一张路由表决定ShardingKey路由到哪一张表 , 每次路由时首先到路由表里查到分片信息 , 再到这个分片去取数据 。
我们分析一个查表法实际案例 。Redis官方在3.0版本之后提供了集群方案Redis Cluster , 其中引入了哈希槽(slot)这个概念 。
一个集群固定有16384个槽 , 在集群初始化时这些槽会平均分配到Redis集群节点上 。每个key请求最终落到哪个槽计算公式是固定的:
SLOT = CRC16(key) mod 16384
那么问题来了:一个key请求过来怎么知道去哪台Redis节点获取数据?这就要用到查表法思想 。
(1) 客户端连接任意一台Redis节点 , 假设随机访问到为节点A(2) 节点A根据key计算出slot值(3) 每个节点都维护着slot和节点映射关系表(4) 如果节点A查表发现该slot在本节点则直接返回数据给客户端(5) 如果节点A查表发现该slot不在本节点则返回给客户端一个重定向命令 , 告诉客户端应该去哪个节点上请求这个key的数据(6) 客户端再向正确节点发起连接请求
查表法优点是可以灵活制定路由策略 , 如果我们发现有的分片已经成为热点则修改路由策略 。缺点是多一次查询路由表操作增加耗时 , 而且路由表如果是单点也可能会有单点问题 。


5.2.3 哈希分片现在比较流行的分片方法是哈希分片 , 相较于范围分片 , 哈希分片可以较为均匀将数据分散在数据库中 。我们现在将订单库拆分为4个库编号为[0,3] , 每个库4张表编号为[0,3] , 如下图如所示:




我们现在使用orderId作为ShardingKey , 那么orderId=100的订单会保存在哪张表?我们来计算一下:由于是分库分表 , 首先确定路由到哪一个库 , 取模计算得到序号为0表示路由到db[0]
db_index = 100 % 4 = 0
库确定了接着在db[0]进行取模表路由
table_index = 100 % 4 = 0
最终这条数据应该路由至下表
db[0]_table[0]
最终计算结果如下图所示:




在实际开发中最终路由到哪张表 , 并不需要我们自己算 , 因为有许多开源框架就可以完成路由功能 , 例如ShardingSphere、TDDL等等 。


6 异现在数据已经使用哈希分片方法完成了水平拆分 , 我们选择的ShardingKey是orderId 。这时客户端需要查询orderId=111的数据 , 查询语句很简单如下:
SELECT * FROM order WHERE orderId = 111
这个语句没有问题 , 因为查询条件包含orderId , 可以路由到具体的数据表 。
现在如果业务想要查询用户维度的数据 , 希望查询userId=222的数据 , 现在问题来了:以下这个语句可以查出数据吗?
SELECT * FROM order WHERE userId = 222
答案是可以 , 但是需要扫描所有库的所有表 , 因为无法根据userId路由到具体某一张表 , 这样时间成本会非常高 , 这种场景怎么办呢?
这就要用到数据异构的思想 。数据异构核心是用空间换时间 , 简单一句话就是一份数据按照不同业务需求保存多份 , 这样做是因为存储硬件成本不是很高 , 而互联网场景对响应速度要求很高 。


以上关于本文的内容,仅作参考!温馨提示:如遇健康、疾病相关的问题,请您及时就医或请专业人士给予相关指导!

「四川龙网」www.sichuanlong.com小编还为您精选了以下内容,希望对您有所帮助: