热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

架构设计之数据分片

数据分片技术作为目前架构设计中处理大数据的一种常规手段,当前被广泛用于缓存、数据库、消息队列等中间件的开发与使用当中,例如在数据量较大的项目当中,系统的性能瓶颈主要来自于与数据库的

数据分片技术作为目前架构设计中处理大数据的一种常规手段,当前被广泛用于缓存、数据库、消息队列等中间件的开发与使用当中,例如在数据量较大的项目当中,系统的性能瓶颈主要来自于与数据库的交互,而通过合理的设计数据库分片规则,可将系统中的数据分布在不同的物理数据库中,平衡了单点的数据量与访问压力,达到提升应用系统数据处理速度的目的,从而提高系统的整体性能;


数据库分片的概念

数据分片概念就是按照一定的规则,将数据集划分成相对独立的数据子集,然后将数据子集分布到不同的节点上,这个节点可以是逻辑上节点,也可以是物理上的节点。数据分片需要按照一定的规则,不同的分布式场景需要设计不同的规则,但基本都遵循同样的原则:按照最主要、最频繁使用的访问方式来分片。在常规的项目开发当中,一般有以下三种方式对数据进行分片:hash方式、一致性hash、按照数据范围,每种分片方式是否适用,一方面需要结合项目的实际情况与规模,另一方面也要从几个常规的维度去评估:

1、 数据分片策略,也就是具体的分片方式

2、 数据分片节点的动态扩展,随着数据量的逐步增长,是否能够通过增加节点来动态扩展适应

3、 数据分片节点的负载均衡‘,结合分片策略能否保证数据均匀的分布在各个节点上以及各个节点的负载压力是否均衡

4、 数据分片的可用性,当其中一个节点产生异常,能否将该节点的数据转移到其他节点上

下面我们就对三种常规的分片模式做个基本的介绍


hash方式

通过对数据(一般为Key值)先进行hash计算再取模的方式是一种简单且使用频繁的分片方式,也就是Hash(Key)%N,这里的N大部分情况下就是我们的结点个数,这种方式相对简单实用,一般场景下能够满足我们的要求。但Hash取模方式主要的问题是节点扩容或缩减的时候,会产生大量的数据迁移,比如从N台设备扩容到N+1台,绝大部分的数据都要在设备间进行迁移。该种方式代码实现较为简单,既可以采用jdk自带的hash方式也可以采用其他hash算法,大家可以自行搜索具体实现。


一致性hash

一致性hash是将数据按照特征值映射到一个首尾相接的hash环上,同时也将节点映射到这个环上。对于数据,从数据在环上的位置开始,顺时针找到的第一个节点即为数据的存储节点。这种模式的优点在于节点一旦需要扩容或缩减的时候只会影响到hash环上相邻的节点,不会发生大规模的数据迁移。分片方式如下图所示

但是常规的一致性hash分片模式也有缺点,一致性hash方式在增加节点的时候,只能分摊一个已存在节点的压力,在其中一个节点挂掉的时候,该节点的压力也会被全部转移到下一个节点。理想的目标是当节点动态发生变化时,已存在的所有节点都能参与进来,达到新的均衡状态。因此在实际开发中一般会引入虚拟节点(virtual node)的概念,即不是将物理节点映射在hash环上,而是将虚拟节点映射到hash环上。虚拟节点的数目远大于物理节点,因此一个物理节点需要负责多个虚拟节点的真实存储。操作数据的时候,先通过hash环找到对应的虚拟节点,再通过虚拟节点与物理节点的映射关系找到对应的物理节点。

引入虚拟节点后的一致性hash需要维护的元数据也会增加:第一,虚拟节点在hash环上的问题,且虚拟节点的数目又比较多;第二,虚拟节点与物理节点的映射关系。但带来的好处是明显的,当一个物理节点失效时,hash环上多个虚拟节点失效,对应的压力也就会发散到多个其余的虚拟节点,事实上也就是多个其余的物理节点。在增加物理节点的时候同样如此。除此之外,可以根据物理节点的性能来调整每一个物理节点对于虚拟节点的数量,充分、合理利用资源。下面看下引入虚拟节点的一致性hash的代码实现

/**
* 节点信息
*
*/
class Node {
private String host;//IP信息
private int load;//负载因子
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getLoad() {
return load;
}
public void setLoad(int load) {
this.load = load;
}
public Node(String host, int load) {
super();
this.host = host;
this.load = load;
}
@Override
public String toString() {
return "Node [host=" + host + ", 负载因子=" + load + "]";
}
}
// 真实节点列表
private static List realNodes = new ArrayList();
// 虚拟节点,key是Hash值,value是虚拟节点信息
private static SortedMap virtualMap = new TreeMap();
static {
//初始化真实节点列表
realNodes.add(new Node("192.168.1.1", 5));
realNodes.add(
new Node("192.168.1.2", 10));
realNodes.add(
new Node("192.168.1.3", 20));
realNodes.add(
new Node("192.168.1.4", 5));
for (Node node : realNodes) { //添加虚拟节点
for (int i = 0; i ) {
String server = node.getHost();
String virtualNode
= server + "&&VN" + i;
int hash = getHash(virtualNode);
virtualMap.put(hash, virtualNode);
}
}
}
/**
* FNV1_32_HASH算法
*/
private static int getHash(String str) {
final int p = 16777619;
int hash = (int) 2166136261L;
for (int i = 0; i )
hash = (hash ^ str.charAt(i)) * p;
hash
+= hash <<13;
hash
^= hash >> 7;
hash
+= hash <<3;
hash
^= hash >> 17;
hash
+= hash <<5;
// 如果算出来的值为负数则取其绝对值
if (hash <0)
hash
= Math.abs(hash);
return hash;
}
/**
* 获取被分配的节点名
*
*
@param node
*
@return
*/
public static Node getNode(String key) {
int hash = getHash(key);//
Integer keyNode = null;
// 得到大于该Hash值的所有Map
SortedMap subMap = virtualMap.tailMap(hash);
if (subMap.isEmpty()) {//在这里形成一个环形结构
//如果没有比该key的hash值大的,则从第一个node开始
keyNode = virtualMap.firstKey();
}
else {
//获取第一个key值,也就是顺时针第一个节点
keyNode = subMap.firstKey();
}
String virtualNode
= virtualMap.get(keyNode);//获取虚拟节点
String realNodeName = virtualNode.substring(0, virtualNode.indexOf("&&"));
for (Node node : realNodes) {//根据虚拟节点获取真实节点
if (node.getHost().equals(realNodeName)) {
return node;
}
}
return null;
}

按数据范围(range based)

按数据范围分片其实也就是基于数据的业务属性进行分片,如唯一编码、时间戳、使用频率等,比如在数据库层面按ID范围、按时间进行分库、分表、分片,按数据被访问频率分为热点库与历史库等方法,都是按数据范围方式的具体应用。基于数据范围的分片模式需要贴合项目实际场景,使用中需要注意以下几点:

1、 分片与扩展实现比较简单,结合ID范围、时间结合业务自行实现即可;

2、较为依赖备份机制,否则某个节点发生异常无法迅速恢复,可用性较难保证;​

3、对数据规模要有前瞻性的评估,例如按时间分片,需要考虑单位时间片内数据分布是否均匀;

4、注意各分片数据之间的性能平衡,因为在常规场景下,无论采用哪种基于数据范围的分片模式,都是距离当前时间点较近的数据被访问和操作的几率较大,所以要特别注意随着数据规模与时间的推移,历史数据规模不断膨胀导致的整体性能下降。

 

综上是对项目开发中我们使用的数据分片模式的一个简单总结,hash与一致性hash有着相对固定的实现方式,按数据范围则需要结合业务数据属性进行分析,我们要意识到数据分片在项目中不是一个孤立的问题,它关系着数据备份、一致性、可用性、负载均衡、数据访问与操作等等一系列问题,所以需要系统性的去学习与思考,本文内容只是一个基础性的阐述与总结,其中如有不足与不正确的地方还望指正与海涵,十分感谢。

 

关注微信公众号,查看更多技术文章。

 



推荐阅读
  • FinOps 与 Serverless 的结合:破解云成本难题
    本文探讨了如何通过 FinOps 实践优化 Serverless 应用的成本管理,提出了首个 Serverless 函数总成本估计模型,并分享了多种有效的成本优化策略。 ... [详细]
  • Netflix利用Druid实现高效实时数据分析
    本文探讨了全球领先的在线娱乐公司Netflix如何通过采用Apache Druid,实现了高效的数据采集、处理和实时分析,从而显著提升了用户体验和业务决策的准确性。文章详细介绍了Netflix在系统架构、数据摄取、管理和查询方面的实践,并展示了Druid在大规模数据处理中的卓越性能。 ... [详细]
  • 优化Flask应用的并发处理:解决Mysql连接过多问题
    本文探讨了在Flask应用中通过优化后端架构来应对高并发请求,特别是针对Mysql 'too many connections' 错误的解决方案。我们将介绍如何利用Redis缓存、Gunicorn多进程和Celery异步任务队列来提升系统的性能和稳定性。 ... [详细]
  • 本文深入探讨了MySQL中常见的面试问题,包括事务隔离级别、存储引擎选择、索引结构及优化等关键知识点。通过详细解析,帮助读者在面对BAT等大厂面试时更加从容。 ... [详细]
  • Spring Cloud因其强大的功能和灵活性,被誉为开发分布式系统的‘一站式’解决方案。它不仅简化了分布式系统中的常见模式实现,还被广泛应用于企业级生产环境中。本书内容详实,覆盖了从微服务基础到Spring Cloud的高级应用,适合各层次的开发者。 ... [详细]
  • 收割机|篇幅_国内最牛逼的笔记,不接受反驳!!
    收割机|篇幅_国内最牛逼的笔记,不接受反驳!! ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 本文探讨了如何在日常工作中通过优化效率和深入研究核心技术,将技术和知识转化为实际收益。文章结合个人经验,分享了提高工作效率、掌握高价值技能以及选择合适工作环境的方法,帮助读者更好地实现技术变现。 ... [详细]
  • 深入解析TCP/IP五层协议
    本文详细介绍了TCP/IP五层协议模型,包括物理层、数据链路层、网络层、传输层和应用层。每层的功能及其相互关系将被逐一解释,帮助读者理解互联网通信的原理。此外,还特别讨论了UDP和TCP协议的特点以及三次握手、四次挥手的过程。 ... [详细]
  • 本文探讨了Java编程的核心要素,特别是其面向对象的特性,并详细介绍了Java虚拟机、类装载器体系结构、Java类文件和Java API等关键技术。这些技术使得Java成为一种功能强大且易于使用的编程语言。 ... [详细]
  • 本文作者分享了在阿里巴巴获得实习offer的经历,包括五轮面试的详细内容和经验总结。其中四轮为技术面试,一轮为HR面试,涵盖了大量的Java技术和项目实践经验。 ... [详细]
  • 阿里云ecs怎么配置php环境,阿里云ecs配置选择 ... [详细]
  • 探讨了在PHP应用中处理多个多对多关系时的MySQL数据库设计方案,特别是如何通过一个统一的连接表来管理这些复杂的关系,并保持数据库的性能和可维护性。 ... [详细]
author-avatar
毒菇求败的zyqy_654
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有