ceph数据分布
ceph的存储是无主结构,数据分布依赖client来计算,有两个条主要路径。
1、数据到PG
2、PG 到OSD
有两个假设: 第一,pg的数量稳定,可以认为保持不变; 第二, OSD的数量可以增减,OSD的存储空间权重不等;
由于 PG的数量保持不变,由数据来找PGID的环节可以简单处理,对数据的key来取hash值再对pg的总数取模即可唯一确认pgid,pgid=hash(data_key)/pg_num。
难点在于从PG到OSD,如果直接用 hash(pgid)/osd_num的模式,则OSD有增减的时候数据就有无规律的迁移,并且也无法体现OSD的不同权重。
Crush算法就是来解决这个问题的,Crush目的是随机跳出一个OSD,并且要满足权重越大的OSD,挑中的概率越大。
每个OSD有不同的容量,比如是4T还是12T的容量,可以根据每个OSD的容量定义它的权重,以T为单位, 比如4T权重设为4,12T则设为12。
如何将PG映射到不同权重的OSD上面?这里可以直接采用CRUSH里面的Straw抽签算法。

核心步骤:
1)计算HASH
draw = CRUSH_HASH( PG_ID, OSD_ID, r ),其中把r当做一个常数,将PG_ID, OSD_ID一起作为输入,得到一个HASH值。
2)增加OSD权重
osd_straw =( draw &0xffff ) * osd_weight
draw &0xffff 得到一个0-65535的数字,再与OSD的权重相乘,以这个作为每个OSD的签长, 权重越大的,数值越大。
3)遍历选取最高的权重
high_draw
Crush所计算出的随机数,是通过HASH得出来,可以保障相同的输入会得出同样的输出结果。
这里只是计算得出了一个OSD,在Ceph集群中是会存在多个副本,如何解决一个PG映射到多个OSD的问题?
将常量r加1, 再去计算一遍,如果和之前的OSD编号不一样, 那么就选取它;如果一样的话,那么再把r+2,再重新计算,直到选出三个不一样的OSD编号。
如果样本容量足够大, 随机数对选中的结果影响逐渐变小, 起决定性的是OSD的权重,OSD的权重越大, 被挑选的概率也就越大。
样本容量足够大,到底是多大? 到底多大才能按照尽可能按照权重来分布,当然是尽量小的样本才好。
样本容量主要由PG和OSD的数量多少来决定,其中最关键的还是OSD数量,如果OSD很少(比如5块盘)也能尽量按照权重分布才好。
PG的数量主要是根据数据预估和OSD的数量来定,有个理论参考数,PG数量 =(OSD数量* 100)/副本数,但是PG数量少影响后面的扩容,太多又占用过多资源,需要有一个平衡。
基于上述考虑,写了一个很简单的程序来验证下数据分布平衡性。
假定OSD数量为5并且权重随机,PG的数量为5000。
结果1:
1.随机生成5个OSDID和对应权重
OSDID=I0N@6nt5pOhjY$g;权重=32.0
OSDID=.nIjl%3zs3aoE7K;权重=16.0
OSDID=S5O9bSS4NMo%qDN;权重=1.0
OSDID=t$lZF91ofuvOKcn;权重=24.0
OSDID=!E2Ia8XE^Jzb5Dz;权重=12.0
2.在pg数量为5000的时候,PG的分布结果:
OSDID=!E2Ia8XE^Jzb5Dz;权重=12.0;拥有的PG数量=625
OSDID=I0N@6nt5pOhjY$g;权重=32.0;拥有的PG数量=2682
OSDID=t$lZF91ofuvOKcn;权重=24.0;拥有的PG数量=1554
OSDID=.nIjl%3zs3aoE7K;权重=16.0;拥有的PG数量=139
结果2:
1.随机生成5个OSDID和对应权重
OSDID=C%EN$UM!e8nZy.R;权重=1.0
OSDID=1iTDBnZeeQ6^Uos;权重=32.0
OSDID=%EMc6a4V5cWi%7D;权重=2.0
OSDID=M7WKDUjLrQaV42D;权重=64.0
OSDID=7OVTO@l$XLE$OV$;权重=8.0
2.在pg数量为5000的时候,PG的分布结果:
OSDID=1iTDBnZeeQ6^Uos;权重=32.0;拥有的PG数量=1201
OSDID=7OVTO@l$XLE$OV$;权重=8.0;拥有的PG数量=18
OSDID=M7WKDUjLrQaV42D;权重=64.0;拥有的PG数量=3781
结果3:
1.随机生成5个OSDID和对应权重
OSDID=TSvabIIG#9IssWW;权重=12.0
OSDID=XglajmN2q3f5qRI;权重=0.8
OSDID=ZEeeX^Wp9tHaxuA;权重=0.5
OSDID=PSiiRAwddyc^ThW;权重=32.0
OSDID=nPI^YbDr0ttVzGa;权重=8.0
2.在pg数量为5000的时候,PG的分布结果:
OSDID=nPI^YbDr0ttVzGa;权重=8.0;拥有的PG数量=319
OSDID=PSiiRAwddyc^ThW;权重=32.0;拥有的PG数量=3816
OSDID=TSvabIIG#9IssWW;权重=12.0;拥有的PG数量=865
package com.test.zhangzk.crush;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;public class TestCephCrush {static String str = "abcdefghijklmnopqrstuvwxyzABCDEDFGHIJKLMNOPQRSTUVWXYZ0123456789.@!#$%^&*";static Float[] factories =new Float[] {0.25f,0.5F,0.8f,1f,2f,4f,8f,12f,16f,20f,24f,32f,64f};static int pgidCount = 5000;static int osdCount = 5;public static void main(String[] args) {List<String> pgidList = getRandomPgIdList(pgidCount);List<OSDBean> osdList = getRandomOSDIdList(osdCount);HashMap<String,Integer> keyCount = new HashMap<String,Integer>();for(int i=0;i<pgidCount;i++) {float maxStraw = 0.0f;float osdFactor = 0.0f;String osdId = "";for( int j=0;j<osdCount;j++) {String key = pgidList.get(i) + osdList.get(j);int hashCode = key.hashCode() & 0xffff;float straw = hashCode * osdList.get(j).getFactor();if( maxStraw < straw) {maxStraw = straw;osdFactor = osdList.get(j).getFactor();osdId = osdList.get(j).getId();}}String key = "OSDID="+osdId + ";权重=" + osdFactor;Integer v = keyCount.get(key);if( v == null ) {keyCount.put(key, 1);}else {keyCount.put(key, v+1);} }System.out.println("2.在pg数量为" + pgidCount +"的时候,PG的分布结果:");for(String k:keyCount.keySet()){System.out.println(k + ";拥有的PG数量=" +keyCount.get(k));}}private static List<String> getRandomPgIdList(int pgidCount){// TODO Auto-generated method stubList<String> pgidList = new ArrayList<String>();java.util.Random r = new Random(System.currentTimeMillis());for( int i=0;i<pgidCount;i++) {StringBuilder sb = new StringBuilder();for( int j=0;j<10;j++) {sb.append(str.charAt(r.nextInt(str.length()-1)));}pgidList.add(sb.toString());}return pgidList;}private static List<OSDBean> getRandomOSDIdList(int osdCount){System.out.println("1.随机生成"+ osdCount + "个OSDID和对应权重");// TODO Auto-generated method stubList<OSDBean> osdList = new ArrayList<OSDBean>();java.util.Random r = new Random(System.currentTimeMillis());for( int i=0;i<osdCount;i++) {StringBuilder sb = new StringBuilder();for( int j=0;j<15;j++) {sb.append(str.charAt(r.nextInt(str.length()-1)));}OSDBean osd = new OSDBean();osd.setId(sb.toString());osd.setFactor(factories[r.nextInt(factories.length)]);System.out.println( "OSDID=" + sb.toString()+ ";权重="+ osd.getFactor() );osdList.add(osd);}return osdList;}
}class OSDBean {private String id;private float factor;public String getId() {return id;}public void setId(String id) {this.id = id;}public float getFactor() {return factor;}public void setFactor(float factor) {this.factor = factor;}
}
相关文章:
ceph数据分布
ceph的存储是无主结构,数据分布依赖client来计算,有两个条主要路径。 1、数据到PG 2、PG 到OSD 有两个假设: 第一,pg的数量稳定,可以认为保持不变; 第二, OSD的数量可以增减,OSD的…...
mysql的两张表left join 进行关联后,索引进行优化案例
一 mysql的案例 1.1 不加索引情况 1.表1没加索引 2.表2没加索引 3.查看索引 1.2 添加索引 1.表1添加索引 2.表2添加索引 3.查看...
2018年3月全国计算机等级考试真题(语言二级C)
2018年3月全国计算机等级考试真题(语言二级C) 第1题 设有定义:char s[81];int i0;以下不能将一行带有空格的字符串正确读入的语句或语句组是 A. while((s[i]getchar())!\n);s[i]\0; B. scanf("%s",s); C.…...
java.util.Timer简介以及简单使用示例
一、简介 定时器(Timer)是一个工具类,用于安排任务(java.util.TimerTask)在指定时间后执行或以指定的时间间隔重复执行。它可以用于执行定时任务、定时调度和时间延迟等操作。 定时器(Timer)可以…...
C语言笔试训练【第12天】
文章目录 1、请阅读以下程序,其运行结果是( )2、假设编译器规定 int 和 short 类型长度分别为32位和16位,若有下列C语言语句,则 y 的机器数为( )3、下列程序的输出结果是什么( &…...
外网连接局域网的几种方式?快解析内网穿透安全便利吗?
外网连接局域网是一项网络连接中的关键技术,它能够让远程用户通过互联网访问内部局域网中的资源和服务。外网连接局域网为企业提供了更大的灵活性和便捷性,但也需要严格的安全措施来防止未经授权的访问。 外网连接局域网的几种方式 在将外网连接到局域…...
基于互斥锁的生产者消费者模型
文章目录 生产者消费者 定义代码实现 / 思路完整代码执行逻辑 / 思路 局部具体分析model.ccfunc(消费者线程) 执行结果 生产者消费者 定义 生产者消费者模型 是一种常用的 并发编程模型 ,用于解决多线程或多进程环境下的协作问题。该模型包含…...
USB隔离器电路分析,SA8338矽塔sytatek电机驱动,源特科技VPS8701,开关电源,电源 大师
一、 USB隔离器电路分析 进行usb隔离可以使用USB隔离模块 ADUM3160 ADUM4160 注意:B0505S 最大带载0.16A,副边需要带载能力需要改变方案 比如移动硬盘至少需要0.5A 用充电宝、18650、设计5V1A输出电源 二、 1A隔离电压方案...
TPC-DS 测试是否支持 Glue Data Catalog?
在上一篇文章《在Hive/Spark上执行TPC-DS基准测试 (PARQUET格式)》中,我们详细介绍了具体的操作方法,当时的集群使用的是Hive Metastore,所有操作均可成功执行。当集群启用 Glue Data Catalog 时,在执行add_constraints.sql时会报错: Optimizing table date_dim (1/24).…...
网络编程(8.14)TCP并发服务器模型
作业: 1. 多线程中的newfd,能否修改成全局,不行,为什么? 2. 多线程中分支线程的newfd能否不另存,直接用指针间接访问主线程中的newfd,不行,为什么? 多线程并发服务器模型原代码&…...
认识负载均衡||WEBSHELL
目录 一、负载均衡 1.nginx负载均衡算法 2.nginx反向代理-负载均衡 二、webshell 1.构造不含数字和字母的webshell 2.如何绕过 一、负载均衡 1.nginx负载均衡算法 (1)轮询(默认)每个请求按时间顺序逐一分配到不同的后端服务&…...
Chapter 15: Object-Oriented Programming | Python for Everybody 讲义笔记_En
文章目录 Python for Everybody课程简介Object-oriented programmingManaging larger programsGetting startedUsing objectsStarting with programsSubdividing a problemOur first Python objectClasses as typesObject lifecycleMultiple instancesInheritanceSummaryGlossa…...
模板编程-成员特化
成员特化:类模板特化除了可以对整个类进行特化外,可以只针对某部分成员函数进行特化 全类特化和成员特化都属于全局特化 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstring>template<typename T> class CMath { public:CMath(const…...
信安通用基础知识
文章目录 密码学经典误区PGP优良保密协议信安经典其它安全手段XSS与CSRF cross site request forgeryCSRF的利用逻辑CSRF示例CSRF防范检查Referer字段添加校验token XSS cross site scripting common weakness enumeration常见密码api误用(摘自毕设参考文献…...
网上购物系统的设计与实现/在线商城/基于spring boot的电商平台/基于Java的商品销售系统
摘 要 本毕业设计的内容是设计并且实现一个基于Springboot的网上购物系统。它是在Windows下,以MYSQL为数据库开发平台,Tomcat网络信息服务作为应用服务器。网上购物系统的功能已基本实现,主要包括用户管理、数码分类管理、数码产品管理、服…...
uniapp项目-配置store文件夹
1.创建store.js 说明:创建一个新的 Vuex Store 实例,配置 Store 中的模块。 import Vue from vue; import Vuex from vuex; // 导入两个 Vuex 模块:moduleCart 和 moduleUser import moduleCart from /store/cart.js; import moduleUser fr…...
element表格多选实现
表格实现多选 实现表格多选很简单,只需要在表格里加上一列即可,加完之后就会在表格里出现一列白色的四方块按钮,可以多选,也可以单选 <el-table-columntype"selection"width"55"align"center"&…...
宠物智能自动喂食器方案设计
据相关数据表明,2019年全国城镇宠物犬猫数量达到9915万只,增幅达到8.4%,消费市场规模达2024亿元,比2018年增长18.5%,整体呈现持续大幅增长的态势。而养宠人群的主力,为25岁至38岁年轻人,都市白领…...
学习笔记230818---对于promise失败状态处理的重要性
问题描述: 在项目中经常会出现如上的问题,这是因为,用promise封装的接口或第三方组件方法,如果只对成功的状态做处理,就会造成页面出错,报error。 解决方法 then()的末尾加上.catch(()>{})对失败的状态…...
【Redis】什么是缓存击穿,如何预防缓存击穿?
【Redis】什么是缓存击穿,如何预防缓存击穿? 缓存击穿是指一个 Key 非常热点,大并发集中对这一个点进行访问,当这个Key 在失效的瞬间,持续的大并发就会穿破缓存,直接请求数据库。缓存击穿和缓存雪崩的区别…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
