简谈RGW的index shard计算
时间:2022-04-25
本文章向大家介绍简谈RGW的index shard计算,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
在RGW里面每个存储到rados的Object都需要先计算出对应元数据存储的shard number,之后再将元数据信息更新到shard number对应的Object里面。代码如下所示
int RGWRados::get_bucket_index_object(const string& bucket_oid_base, const string& obj_key,
uint32_t num_shards, RGWBucketInfo::BIShardsHashType hash_type, string *bucket_obj, int *shard_id)
{
int r = 0;
switch (hash_type) {
case RGWBucketInfo::MOD:
if (!num_shards) {
// By default with no sharding, we use the bucket oid as itself
(*bucket_obj) = bucket_oid_base;
if (shard_id) {
*shard_id = -1;
}
} else { uint32_t sid = ceph_str_hash_linux(obj_key.c_str(), obj_key.size());
uint32_t sid2 = sid ^ ((sid & 0xFF) << 24);
sid = sid2 % MAX_BUCKET_INDEX_SHARDS_PRIME % num_shards;
char buf[bucket_oid_base.size() + 32];
snprintf(buf, sizeof(buf), "%s.%d", bucket_oid_base.c_str(), sid);
(*bucket_obj) = buf;
if (shard_id) {
*shard_id = (int)sid;
}
}
break;
default:
r = -ENOTSUP;
}
return r;
}
有同学提问,为什么不直接写成 sid = sid %num_shards,而是获取到对应sid以后再做一次sid2 = sid ^ ((sid & 0xFF) << 24),下面把这段代码截取出来说明原因。
编辑头文件 hash_shard.h,内容如下
#ifndef hash_shard_h
#define hash_shard_h
#ifndef _UINT32_T
#define _UINT32_T
typedef unsigned int uint32_t;
#endif /* _UINT32_T */
#endif /* hash_shard_h */
unsigned ceph_str_hash_linux(const char *str, unsigned long length)
{
unsigned long hash = 0;
while (length--) {
unsigned char c = *str++;
hash = (hash + (c << 4) + (c >> 4)) * 11;
}
return hash;
}
编辑 main.cpp,内容如下
#include <iostream>
#include "hash_shard.h"
void hash_obj(std::string obj_key){
uint32_t sid = ceph_str_hash_linux(obj_key.c_str(), obj_key.size());
uint32_t sid1 = sid ^ ((sid & 0xFF) << 24);
uint32_t sid2 = sid1 % 7877 % 8;
uint32_t sid3 = sid % 7877 % 8;
std::cout << "hash2=" << sid2 <<std::endl;
std::cout << "hash1="<< sid3 <<std::endl;
}
int main(int argc, const char * argv[]) {
std::string obj_key1 = "aa2";
hash_obj(obj_key1);
std::string obj_key2 = "aa1";
hash_obj(obj_key2);
std::string obj_key3 = "aa0";
hash_obj(obj_key3);
std::string obj_key4 = "aa3";
hash_obj(obj_key4);
std::string obj_key5 = "aa3";
hash_obj(obj_key5);
return 0;
}
root@demohost:/home/demouser/hash_shard# g++ main.cpp -o hash_shard
root@demohost:/home/demouser/hash_shard# ./hash_shard
hash2=7hash1=1hash2=7hash1=1hash2=7hash1=1hash2=4hash1=1hash2=4hash1=1
从裁剪出来的代码运行结果来看,直接sid = sid %num_shards会导致hash计算出来的结果不够离散,最终导致数据都集中写到一个shard文件上造成写入上的单点热数据(hash1计算出来的结果都是1)。
另外MAX_BUCKET_INDEX_SHARDS_PRIME为什么是7877,可以是其他数吗?答案是可以的,但是这个最好是质数,从而保障取余得到的结果足够随机。
- hihoCoder #1498 : Diligent Robots【数学】
- Codeforces Round #336 (Div. 2)【A.思维,暴力,B.字符串,暴搜,前缀和,C.暴力,D,区间dp,E,字符串,数学】
- 【防护】如何阻止SELECT * 语句
- COGS 862. 二进制数01串【dp+经典二分+字符串】
- 【AlphaGo Zero 核心技术-深度强化学习教程代码实战03】编写通用的格子世界环境类
- 冒泡排序简单操作模版及实例分析
- COGS 1299. bplusa【听说比a+b还要水的大水题???】
- python学习笔记之运算符
- 锐捷网络NBR部分路由器cookie欺骗权限绕过
- 手写快排模版
- COGS 68. [NOIP2005] 采药【01背包复习】
- UESTC 30 &&HDU 2544最短路【Floyd求解裸题】
- 我的第一个网页制作:Hello World!
- UESTC 1584 Washi与Sonochi的约定【树状数组裸题+排序】
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法