In RGW, each Object stored in RADOS needs to first calculate the shard number of the corresponding metadata store, and then update the metadata information to the corresponding Object of the Shard number. The code is shown below
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; }Copy the code
Sid = sid %num_shards sid = sid ^ (sid & 0xFF) << 24) sid = sid %num_shards
Edit the header file hash_shard. H as follows
#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;
}
Copy the code
Edit main. CPP as follows
#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=7
hash1=1
hash2=7
hash1=1
hash2=7
hash1=1
hash2=4
hash1=1
hash2=4
hash1=1
Copy the code
From the clipped code, direct SID = sid %num_shards results in insufficiently discrete hash results, resulting in single hot writes to a single shard file (hash1 results in 1).
MAX_BUCKET_INDEX_SHARDS_PRIME 7877? The answer is yes, but it better be prime, so that the mod is random enough.