技术心得记录:架构设计之数据分片

简介: 技术心得记录:架构设计之数据分片

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


数据库分片的概念


数据分片概念就是按照一定的规则,将数据集划分成相对独立的数据子集,然后将数据子集分布到不同的节点上,这个节点可以是逻辑上节点,也可以是物理上的节点。数据分片需要按照一定的规则,不同的分布式场景需要设计不同的规则,但基本都遵循同样的原则:按照最主要、最频繁使用的访问方式来分片。在常规的项目开发当中,一般有以下三种方式对数据进行分片: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));


//代码效果参考:http://www.jhylw.com.cn/233722673.html

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

相关文章
|
30天前
|
Kubernetes Cloud Native 微服务
探索云原生技术:容器化与微服务架构的融合之旅
本文将带领读者深入了解云原生技术的核心概念,特别是容器化和微服务架构如何相辅相成,共同构建现代软件系统。我们将通过实际代码示例,探讨如何在云平台上部署和管理微服务,以及如何使用容器编排工具来自动化这一过程。文章旨在为开发者和技术决策者提供实用的指导,帮助他们在云原生时代中更好地设计、部署和维护应用。
|
2月前
|
消息中间件 存储 缓存
十万订单每秒热点数据架构优化实践深度解析
【11月更文挑战第20天】随着互联网技术的飞速发展,电子商务平台在高峰时段需要处理海量订单,这对系统的性能、稳定性和扩展性提出了极高的要求。尤其是在“双十一”、“618”等大型促销活动中,每秒需要处理数万甚至数十万笔订单,这对系统的热点数据处理能力构成了严峻挑战。本文将深入探讨如何优化架构以应对每秒十万订单级别的热点数据处理,从历史背景、功能点、业务场景、底层原理以及使用Java模拟示例等多个维度进行剖析。
58 8
|
23天前
|
监控 安全 API
使用PaliGemma2构建多模态目标检测系统:从架构设计到性能优化的技术实践指南
本文详细介绍了PaliGemma2模型的微调流程及其在目标检测任务中的应用。PaliGemma2通过整合SigLIP-So400m视觉编码器与Gemma 2系列语言模型,实现了多模态数据的高效处理。文章涵盖了开发环境构建、数据集预处理、模型初始化与配置、数据加载系统实现、模型微调、推理与评估系统以及性能分析与优化策略等内容。特别强调了计算资源优化、训练过程监控和自动化优化流程的重要性,为机器学习工程师和研究人员提供了系统化的技术方案。
145 77
使用PaliGemma2构建多模态目标检测系统:从架构设计到性能优化的技术实践指南
|
30天前
|
运维 Cloud Native 持续交付
云原生技术深度探索:重塑现代IT架构的无形之力####
本文深入剖析了云原生技术的核心概念、关键技术组件及其对现代IT架构变革的深远影响。通过实例解析,揭示云原生如何促进企业实现敏捷开发、弹性伸缩与成本优化,为数字化转型提供强有力的技术支撑。不同于传统综述,本摘要直接聚焦于云原生技术的价值本质,旨在为读者构建一个宏观且具体的技术蓝图。 ####
|
2月前
|
Cloud Native 持续交付 云计算
云原生技术在现代IT架构中的转型力量####
本文深入剖析了云原生技术的精髓,探讨其在现代IT架构转型中的关键作用与实践路径。通过具体案例分析,展示了云原生如何赋能企业实现更高效的资源利用、更快的迭代速度以及更强的系统稳定性,为读者提供了一套可借鉴的实施框架与策略。 ####
27 0
|
2月前
|
运维 Kubernetes Docker
深入理解容器化技术及其在微服务架构中的应用
深入理解容器化技术及其在微服务架构中的应用
66 1
|
2月前
|
监控 Java 微服务
从零构建微服务架构:一次深度技术探索之旅####
本文作为一篇深度技术分享,引领读者踏上自底向上搭建微服务架构的征途,旨在通过实战经验剖析,揭示微服务转型背后的技术挑战与解决方案。不同于常规摘要仅概述内容,本文摘要将直接以故事化手法,简述作者从单体应用困境出发,逐步迈向微服务化的心路历程,涵盖关键决策点、技术选型考量及实践收获,激发读者对微服务架构设计与实现的浓厚兴趣。 ####
|
2月前
|
Cloud Native 持续交付 云计算
深入理解云原生技术及其在现代IT架构中的应用
在数字化浪潮的推动下,云原生技术已成为企业转型的关键。本文将通过浅显易懂的语言和生动的比喻,带领读者探索云原生的核心概念、优势以及如何在企业中实现云原生架构。我们将一起揭开云原生的神秘面纱,了解它如何助力企业快速适应市场变化,提升业务的灵活性和创新能力。
|
2月前
|
敏捷开发 缓存 中间件
.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素
本文深入探讨了.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素,并通过企业级应用和Web应用开发的实践案例,展示了如何在实际项目中应用这些模式,旨在为开发者提供有益的参考和指导。
40 3
|
2月前
|
Cloud Native 云计算 Docker
云原生技术的崛起:从容器化到微服务架构
云原生技术的崛起:从容器化到微服务架构

热门文章

最新文章