Skip to content

Commit

Permalink
support bkdrabscrc32
Browse files Browse the repository at this point in the history
  • Loading branch information
hustfisher committed Oct 30, 2023
1 parent 0895bce commit e5df582
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 0 deletions.
46 changes: 46 additions & 0 deletions sharding/src/hash/bkdrabscrc32.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use super::{bkdr::Bkdr, crc32::Crc32, Hash};

/// key:${num}#suffix,对数字部分进行 bkdr + abs + crc32;属小众业务算法。
/// 对于i32溢出,一般有类型提升 vs abs两种策略,bkdr自身是有abs,但考虑避免后面bkdr符号变化的影响,此处仍然进行abs;
#[derive(Debug, Clone)]
pub struct BkdrAbsCrc32 {
bkdr: Bkdr,
crc32: Crc32,
}

impl Default for BkdrAbsCrc32 {
fn default() -> Self {
Self {
bkdr: Default::default(),
crc32: Default::default(),
}
}
}

impl Hash for BkdrAbsCrc32 {
fn hash<S: super::HashKey>(&self, key: &S) -> i64 {
// 定位到num结束的位置,拿到hashkey
let mut hash_key = String::with_capacity(key.len());
for i in 0..key.len() {
let c = key.at(i);
if c.is_ascii_digit() {
hash_key.push(c as char);
} else {
// 遇到第一个非数字停止
break;
}
}

if hash_key.len() == 0 {
log::warn!("found malformed bkdrabscrc32 key:{:?}", key);
return 0;
}

// bkdr
let hash = self.bkdr.hash(&hash_key.as_bytes());
// abs + string
let hash_abs = hash.abs().to_string();
// crc32
self.crc32.hash(&hash_abs.as_bytes())
}
}
4 changes: 4 additions & 0 deletions sharding/src/hash/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod bkdr;
pub mod bkdrabscrc32;
pub mod bkdrsub;
pub mod crc32;
pub mod crc32local;
Expand All @@ -11,6 +12,7 @@ pub mod rawcrc32local;
pub mod rawsuffix;

pub use bkdr::Bkdr;
pub use bkdrabscrc32::BkdrAbsCrc32;
pub use crc32::*;
pub use crc32local::*;
pub use lbcrc32local::LBCrc32localDelimiter;
Expand Down Expand Up @@ -66,6 +68,7 @@ pub enum Hasher {
Raw(Raw), // redis raw, long型字符串直接用数字作为hash
Bkdr(Bkdr),
Bkdrsub(Bkdrsub),
BkdrAbsCrc32(BkdrAbsCrc32), // 混合三种hash:先bkdr,再abs,最后进行crc32计算
Crc32(Crc32),
Crc32Short(Crc32Short), // mc short crc32
Crc32Num(Crc32Num), // crc32 for a hash key whick is a num,
Expand Down Expand Up @@ -114,6 +117,7 @@ impl Hasher {
HASH_PADDING => Self::Padding(Default::default()),
"bkdr" => Self::Bkdr(Default::default()),
"bkdrsub" => Self::Bkdrsub(Default::default()),
"bkdrabscrc32" => Self::BkdrAbsCrc32(Default::default()),
"raw" => Self::Raw(Raw::from(Default::default())),
"crc32" => Self::Crc32(Default::default()),
"crc32local" => Self::Crc32local(Default::default()),
Expand Down
12 changes: 12 additions & 0 deletions tests/src/hash_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,16 @@ mod hash_test {
println!("key:{}, crc64: {}, dist: {}", key, crc, idx);
assert_eq!(-7536761181773004100_i64, crc);
}

#[test]
fn bkdrabscrc32() {
let hasher = Hasher::from("bkdrabscrc32");
let key1 = "1234567890#123";
let key2 = "1234567890Abc";

let hash1 = hasher.hash(&key1.as_bytes());
let hash2 = hasher.hash(&key2.as_bytes());
println!("bkdrabscrc32: {} : {}", hash1, hash2);
assert_eq!(hash1, hash2);
}
}

0 comments on commit e5df582

Please sign in to comment.