diff --git a/sharding/src/hash/bkdrsub.rs b/sharding/src/hash/bkdrsub.rs index 46dedbd7d..0e932d865 100644 --- a/sharding/src/hash/bkdrsub.rs +++ b/sharding/src/hash/bkdrsub.rs @@ -1,14 +1,24 @@ ///
用于支持key中部分字符串做hashkey,且hash算法类似bkdr的hash算法;
-/// key格式:abc#123_456,hashkey则是‘#’之后、‘_’之前的内容;
-/// 格式注意:'#'需要存在,否则hashkey为空;'_'可能不存在,如果'_'不存在,则'#'之后的全部是hashkey
+/// hashkey是‘#’之后、$delimiter之前的内容; +/// 例如key:abc#123_456 +/// 如果$delimiter是'_',则hashkey是123; +/// 如果$delimiter是'^',则hashkey是123_456; +/// 格式注意:'#'需要存在,否则hashkey为空;$delimiter可能不存在,如果$delimiter不存在,则'#'之后的全部是hashkey #[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(&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; @@ -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; } diff --git a/sharding/src/hash/mod.rs b/sharding/src/hash/mod.rs index 3dc101178..fb2e2dd6e 100644 --- a/sharding/src/hash/mod.rs +++ b/sharding/src/hash/mod.rs @@ -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等业务使用 @@ -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 @@ -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()), diff --git a/tests/src/bkdrsub.rs b/tests/src/bkdrsub.rs index 732aa4aec..4e15b508d 100644 --- a/tests/src/bkdrsub.rs +++ b/tests/src/bkdrsub.rs @@ -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() { diff --git a/tests/src/hash_test.rs b/tests/src/hash_test.rs index 0d3141aed..18fd11262 100644 --- a/tests/src/hash_test.rs +++ b/tests/src/hash_test.rs @@ -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); }