- 哈希取模算法:
- 原理:通过对某个字段(如用户ID)的哈希值进行取模运算,将数据均匀地分布到不同的库或表中。
- 使用场景:适用于数据量大且分布均匀的场景,常用于用户中心等系统。
- 优点:
- 数据分布均匀,有利于负载均衡。
- 横向扩展方便,只需增加新的表或数据库实例。
- 缺点:
- 当需要扩容或缩容时,需要重新计算哈希值,可能导致数据迁移和重新分布,影响性能。
- 不便于历史数据的归档。
- 举例:假设有一个用户中心系统,用户ID从1开始递增。可以使用哈希取模算法将用户数据分布到多个数据库实例中,如
hash(用户ID) mod 4
,这样用户ID为1、5、9...的用户数据会被分布到第一个数据库,用户ID为2、6、10...的用户数据会被分布到第二个数据库,以此类推。
- 范围分区算法:
- 原理:根据某个字段的范围(如时间、ID等)将数据分布到不同的库或表中。
- 使用场景:适用于数据分布不均或需要按照一定顺序查询的场景,如订单中心等。
- 优点:
- 数据分区明确,便于管理和查询。
- 适用于按时间或ID等顺序查询的场景。
- 缺点:
- 如果数据分布不均匀,可能导致某些库或表的负载过重。
- 扩展性相对较差,因为可能需要重新调整分区范围。
- 举例:在订单中心系统中,可以根据订单ID的范围将数据分布到不同的表中。例如,订单ID为1-10000的订单数据存储在表1中,订单ID为10001-20000的订单数据存储在表2中,以此类推。
- 一致性哈希算法:
- 原理:一致性哈希算法(Consistent Hashing)是在1997年由麻省理工学院提出的一种特殊的哈希算法,主要用于解决分布式缓存的问题。它的主要目标是在移除或添加一个服务器时,能够尽可能小地改变已存在的服务请求与处理请求服务器之间的映射关系。这解决了简单哈希算法在分布式哈希表(DHT)中存在的动态伸缩问题。
- 使用场景:在分布式系统中,数据通常存储在多个节点中,而这些节点的状态可能是不稳定的,可能随时有节点上线或下线。一致性哈希算法就是在这样的不稳定环境中保证数据的正确命中,避免因节点数量的变化而导致大部分数据的失效。
- 优点:
- 在节点增减时,只需要重新分配影响到的数据,对整体数据的影响较小。
- 通过虚拟节点的引入,可以进一步提高数据分布的均匀性和系统的容错性。
- 缺点:
- 当节点数量变化较大时,仍然会有较多的数据迁移。
- 一致性哈希算法需要维护一个完整的节点列表,对于大规模分布式系统来说,这个列表的维护成本较高。
- 举例:假设我们有一个分布式缓存系统,其中包含4个缓存节点(Node A、Node B、Node C、Node D),并且我们使用一致性哈希算法来分配缓存数据。
- 首先,我们构建一个虚拟的哈希环,这个环可以想象成一个闭合的圆环,从0到2^32-1的值都均匀分布在这个环上。
- 接下来,我们将每个缓存节点的哈希值计算出来,并映射到哈希环上。例如,Node A的哈希值映射到环上的位置是5,Node B的哈希值映射到环上的位置是100,依此类推。
- 当我们需要存储一个数据项时,我们计算该数据项的哈希值,并确定它在哈希环上的位置。然后,我们沿着环顺时针查找,找到第一个遇到的缓存节点,将该数据项存储在该节点上。例如,如果数据项X的哈希值映射到环上的位置是80,那么数据项X将被存储在Node B上,因为它是顺时针方向上遇到的第一个节点。
- 如果某个缓存节点出现故障或需要扩容/缩容,一致性哈希算法会重新计算受影响的数据项的哈希值,并将它们迁移到新的节点上。由于一致性哈希算法的特性,这种迁移只会影响很小一部分数据项,从而减少了数据迁移的开销。
- 目录式路由算法:
- 原理:目录式路由算法是一种采用较多的简单算法,也称为固定式算法。在这种算法中,网络内的每个节点交换机内都保存有一个从此节点到其他节点的路由表。这个路由表由网络设计者根据网络拓扑或其他因素人工编制,并在网络投入运行之前就存入节点交换机的存储器内,网络在运行中此表始终不变。
- 使用场景:目录式路由算法适用于网络结构相对固定,且节点数量不太多的场景。例如,在早期的P2P网络中,如Napster,就采用了目录式路由算法。每个节点在加入网络时,都会将自己的信息(如IP地址、端口号、共享文件目录等)告诉中心服务器,并由中心服务器维护一个全局的路由表。当节点需要查询文件时,会向中心服务器发出请求,中心服务器根据路由表返回查询结果。
- 优点:
- 结构简单,实现容易。
- 对于网络结构固定的场景,查询效率较高。
- 缺点:
- 扩展性差。随着网络规模的增大,中心服务器的负担会越来越重,可能成为网络继续扩张的瓶颈。
- 节点之间的通信需要经过中心服务器,可能存在单点故障的风险。
- 举例:假设我们有一个简单的P2P文件共享网络,其中包含5个节点(Node 1、Node 2、Node 3、Node 4、Node 5)。每个节点都维护一个文件目录,并共享自己的文件给其他节点。
- 当节点Node 1想要查询一个特定的文件时,它会向中心服务器发送一个查询请求,请求中包含要查询的文件名。
- 中心服务器接收到查询请求后,查找其维护的全局路由表,找到拥有该文件的其他节点列表。假设该文件在Node 3和Node 4上有共享。
- 中心服务器将查询结果返回给Node 1,Node 1收到结果后,直接与Node 3和Node 4建立连接,并从它们那里下载所需的文件。
- 如果新节点加入网络或现有节点离开网络,中心服务器会更新其全局路由表,以反映最新的网络拓扑结构。这样,其他节点在发起查询时就能得到最新的节点列表。
前两种加在一起
范围 + 取模算法
将范围拆分和取模算法结合起来使用。
- 将数据按照范围放到不同的数据库中。
- 取模运算,将数据分配到不同的数据表中。
总结:
分库分表是一种数据库设计技术,其目的是为了提高数据库的性能和扩展性。它通过将数据库的表拆分到多个数据库中来实现这一目的。
要根据实际的业务情况进行组合,例如省、市;男、女;年龄;等等都可以作为策略。
- 增加了系统的复杂性:分库分表会增加系统的复杂性,有时候需要额外的中间件(MyCat)来实现,并且需要在程序中额外处理分库分表的逻辑。分页、排序、跨节点联合查询等等问题。
- 降低了事务的原子性:由于分库分表会将数据存储在多个数据库或表中,因此在一次事务中可能涉及多个数据库,降低了事务的原子性。如何解决跨库事务问题。
- 对性能的影响不确定:分库分表并不是一定能提高性能,具体的性能提升取决于实际情况,如果没有正确地进行分库分表,可能会导致性能下降。
- 需要进行数据迁移:如果需要扩展分库分表的范围,可能需要进行数据迁移,这会增加系统的复杂性和风险。
总之,分库分表有一些优点,但同时也有一些缺点,在实际应用中需要谨慎考虑。
注:目录式路由算法在实际应用中可能并不常见,因为它存在扩展性差和单点故障等问题
分布式系统更倾向于使用更复杂的路由算法,如一致性哈希算法、Kademlia算法等。