Skip to content

Commit

Permalink
Merge pull request #495 from weibocom/bkdrsubh
Browse files Browse the repository at this point in the history
增加hash方法bkdrsubhat
  • Loading branch information
parabala authored Oct 25, 2024
2 parents 99b481a + c0952a5 commit 272daec
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 12 deletions.
22 changes: 16 additions & 6 deletions sharding/src/hash/bkdrsub.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
/// <pre>用于支持key中部分字符串做hashkey,且hash算法类似bkdr的hash算法;
/// key格式:abc#123_456,hashkey则是‘#’之后、‘_’之前的内容;
/// 格式注意:'#'需要存在,否则hashkey为空;'_'可能不存在,如果'_'不存在,则'#'之后的全部是hashkey</pre>
/// hashkey是‘#’之后、$delimiter之前的内容;
/// 例如key:abc#123_456
/// 如果$delimiter是'_',则hashkey是123;
/// 如果$delimiter是'^',则hashkey是123_456;
/// 格式注意:'#'需要存在,否则hashkey为空;$delimiter可能不存在,如果$delimiter不存在,则'#'之后的全部是hashkey</pre>
#[derive(Clone, Default, Debug)]
pub struct Bkdrsub;
pub struct BkdrsubDelimiter {
delimiter: u8,
}
impl BkdrsubDelimiter {
pub fn from(delimiter: u8) -> Self {
Self { delimiter }
}
}

impl super::Hash for Bkdrsub {
impl super::Hash for BkdrsubDelimiter {
fn hash<S: super::HashKey>(&self, key: &S) -> i64 {
const SEED: i32 = 131; // 31 131 1313 13131 131313 etc..
const START_CHAR_VAL: u8 = '#' as u8;
const END_CHAR_VAL: u8 = '_' as u8;
let end_char_val: u8 = self.delimiter;

let mut hash = 0_i32;
let mut found_start_char = false;
Expand All @@ -17,7 +27,7 @@ impl super::Hash for Bkdrsub {
let c = key.at(i);
if found_start_char {
// hashkey 计算
if c != END_CHAR_VAL {
if c != end_char_val {
hash = hash.wrapping_mul(SEED).wrapping_add(c as i32);
continue;
}
Expand Down
7 changes: 4 additions & 3 deletions sharding/src/hash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub use rawsuffix::RawSuffix;

pub mod crc;

use self::{bkdrsub::Bkdrsub, crc64::Crc64, fnv1::Fnv1F32, fnv1::Fnv1aF64};
use self::{bkdrsub::BkdrsubDelimiter, crc64::Crc64, fnv1::Fnv1F32, fnv1::Fnv1aF64};
use enum_dispatch::enum_dispatch;

// 占位hash,主要用于兼容服务框架,供mq等业务使用
Expand Down Expand Up @@ -69,7 +69,7 @@ pub enum Hasher {
Padding(Padding),
Raw(Raw), // redis raw, long型字符串直接用数字作为hash
Bkdr(Bkdr),
Bkdrsub(Bkdrsub),
BkdrsubDelimiter(BkdrsubDelimiter),
BkdrAbsCrc32(BkdrAbsCrc32), // 混合三种hash:先bkdr,再abs,最后进行crc32计算
Crc32(Crc32),
Crc32Short(Crc32Short), // mc short crc32
Expand Down Expand Up @@ -120,7 +120,8 @@ impl Hasher {
return match alg_parts[0] {
HASH_PADDING => Self::Padding(Default::default()),
"bkdr" => Self::Bkdr(Default::default()),
"bkdrsub" => Self::Bkdrsub(Default::default()),
"bkdrsub" => Self::BkdrsubDelimiter(BkdrsubDelimiter::from('_' as u8)),
"bkdrsubhat" => Self::BkdrsubDelimiter(BkdrsubDelimiter::from('^' as u8)),
"bkdrabscrc32" => Self::BkdrAbsCrc32(Default::default()),
"raw" => Self::Raw(Raw::from(Default::default())),
"crc32" => Self::Crc32(Default::default()),
Expand Down
17 changes: 16 additions & 1 deletion tests/src/bkdrsub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,24 @@ fn bkdrsub_one() {
let dist = Distribute::from("modrange-8640", &servers);
let dist_idx = dist.index(hash1);

println!("key:{}, hash:{}, idx:{}", key1, hash1, dist_idx);
println!("bkdrsub key:{}, hash:{}, idx:{}", key1, hash1, dist_idx);
assert_eq!(dist_idx, 905)
}
#[test]
fn bkdrsubhat_one() {
let hasher = Hasher::from("bkdrsubhat");

let key1 = "otdn#1042015:carSubBrand^e4ab74c125e9e95edad691ffe9820118";
let hash1 = hasher.hash(&key1.as_bytes());

let shards = 1080;
let servers = vec!["padding".to_string(); shards];
let dist = Distribute::from("modrange-8640", &servers);
let dist_idx = dist.index(hash1);

println!("bkdrsubhat key:{}, hash:{}, idx:{}", key1, hash1, dist_idx);
assert_eq!(dist_idx, 905)
}
// TODO 临时批量文件的hash、dist校验测试,按需打开
#[test]
fn bkdrsub_dist() {
Expand Down
18 changes: 16 additions & 2 deletions tests/src/hash_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,26 @@ mod hash_test {

let key1 = "abc#12345678901234567";
let hash1 = hasher.hash(&key1.as_bytes());
println!("key:{}, hash:{}", key1, hash1);
println!("bkdrsub key:{}, hash:{}", key1, hash1);
assert_eq!(hash1, 1108486745);

let key2 = "abc#12345678901234567_123456";
let hash2 = hasher.hash(&key2.as_bytes());
println!("key:{}, hash:{}", key2, hash2);
println!("bkdrsub key:{}, hash:{}", key2, hash2);
assert_eq!(hash2, 1108486745);
}
#[test]
fn bkdrsubhat() {
let hasher = Hasher::from("bkdrsubhat");

let key1 = "abc#12345678901234567";
let hash1 = hasher.hash(&key1.as_bytes());
println!("bkdrsubhat key:{}, hash:{}", key1, hash1);
assert_eq!(hash1, 1108486745);

let key2 = "abc#12345678901234567^123456";
let hash2 = hasher.hash(&key2.as_bytes());
println!("bkdrsubhat key:{}, hash:{}", key2, hash2);
assert_eq!(hash2, 1108486745);
}

Expand Down

0 comments on commit 272daec

Please sign in to comment.