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

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

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


数据库分片的概念


数据分片概念就是按照一定的规则,将数据集划分成相对独立的数据子集,然后将数据子集分布到不同的节点上,这个节点可以是逻辑上节点,也可以是物理上的节点。数据分片需要按照一定的规则,不同的分布式场景需要设计不同的规则,但基本都遵循同样的原则:按照最主要、最频繁使用的访问方式来分片。在常规的项目开发当中,一般有以下三种方式对数据进行分片: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有着相对固定的实现方式,按数据范围则需要结合业务数据属性进行分析,我们要意识到数据分片在项目中不是一个孤立的问题,它关系着数据备份、一致性、可用性、负载均衡、数据访问与操作等等一系列问题,所以需要系统性的去学习与思考,本文内容只是一个基础性的阐述与总结,其中如有不足与不正确的地方还望指正与海涵,十分感谢。

相关文章
|
2月前
|
数据采集 缓存 前端开发
如何开发门店业绩上报管理系统中的商品数据板块?(附架构图+流程图+代码参考)
本文深入讲解门店业绩上报系统中商品数据板块的设计与实现,涵盖商品类别、信息、档案等内容,详细阐述技术架构、业务流程、数据库设计及开发技巧,并提供完整代码示例,助力企业构建稳定、可扩展的商品数据系统。
|
19天前
|
数据采集 机器学习/深度学习 搜索推荐
MIT新论文:数据即上限,扩散模型的关键能力来自图像统计规律,而非复杂架构
MIT与丰田研究院研究发现,扩散模型的“局部性”并非源于网络架构的精巧设计,而是自然图像统计规律的产物。通过线性模型仅学习像素相关性,即可复现U-Net般的局部敏感模式,揭示数据本身蕴含生成“魔法”。
91 3
MIT新论文:数据即上限,扩散模型的关键能力来自图像统计规律,而非复杂架构
|
2月前
|
机器学习/深度学习 存储 人工智能
RAG系统文本检索优化:Cross-Encoder与Bi-Encoder架构技术对比与选择指南
本文将深入分析这两种编码架构的技术原理、数学基础、实现流程以及各自的优势与局限性,并探讨混合架构的应用策略。
171 10
RAG系统文本检索优化:Cross-Encoder与Bi-Encoder架构技术对比与选择指南
|
29天前
|
JSON 供应链 监控
1688商品详情API技术深度解析:从接口架构到数据融合实战
1688商品详情API(item_get接口)可通过商品ID获取标题、价格、库存、SKU等核心数据,适用于价格监控、供应链管理等场景。支持JSON格式返回,需企业认证。Python示例展示如何调用接口获取商品信息。
|
1月前
|
数据可视化 前端开发 数据管理
什么是低代码?一文看懂:低代码技术的发展历程及技术架构
低代码开发平台通过可视化界面与组件化设计,大幅降低编程门槛,使开发者无需大量编码即可快速构建应用。它具备可视化开发、预制组件、低技术门槛及全流程支持等核心特征,适用于业务流程自动化、数据管理、客户关系管理等多种场景。自萌芽期至今,低代码不断演进,成为企业数字化转型的重要工具,显著提升开发效率、降低成本,并推动全民开发者时代的到来。
299 0
什么是低代码?一文看懂:低代码技术的发展历程及技术架构
|
2月前
|
数据采集 监控 数据可视化
数据量暴涨时,抓取架构该如何应对?——豆瓣电影案例调研
本案例讲述了在豆瓣电影数据采集过程中,面对数据量激增和限制机制带来的挑战,如何通过引入爬虫代理、分布式架构与异步IO等技术手段,实现采集系统的优化与扩展,最终支撑起百万级请求的稳定抓取。
数据量暴涨时,抓取架构该如何应对?——豆瓣电影案例调研
|
2月前
|
缓存 前端开发 BI
如何开发门店业绩上报管理系统中的门店数据板块?(附架构图+流程图+代码参考)
门店业绩上报管理是将门店营业、动销、人效等数据按标准化流程上报至企业中台或BI系统,用于考核、分析和决策。其核心在于构建“数据底座”,涵盖门店信息管理、数据采集、校验、汇总与对接。实现时需解决数据脏、上报慢、分析无据等问题。本文详解了实现路径,包括系统架构、数据模型、业务流程、开发要点、三大代码块(数据库、后端、前端)及FAQ,助你构建高效门店数据管理体系。
|
2月前
|
SQL 数据采集 数据处理
终于有人把数据架构讲清楚了!
本文深入浅出地解析了数据架构的核心逻辑,涵盖其定义、作用、设计方法及常见误区,助力读者构建贴合业务的数据架构。
|
2月前
|
机器学习/深度学习 人工智能 Java
Java 技术支撑下 AI 与 ML 技术融合的架构设计与落地案例分析
摘要: Java与AI/ML技术的融合为智能化应用提供了强大支持。通过选用Deeplearning4j、DJL等框架解决技术适配问题,并结合Spring生态和JVM优化提升性能。在金融风控、智能制造、医疗影像等领域实现了显著效果,如审批效率提升3倍、设备停机减少41%、医疗诊断延迟降低80%。这种技术融合推动了多行业的智能化升级,展现了广阔的应用前景。
163 0
|
10月前
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。

热门文章

最新文章