Redis-hashtag

199 阅读1分钟

背景

在redis集群中,一个key会计算crc16值后,经过一致性hash分配到一个slot上,如果想按key的前缀,将相同的前缀的key都分配到一个槽上,可以使用hashtag

hashtag 如何实现

{}中的部分参与crc16的值计算

// 源码位置
// https://github.com/redis/redis/blob/6.2.6/src/cluster.c
unsigned int keyHashSlot(char *key, int keylen) {
    // s代表{在key中的位置,e代表}在key中的位置
    int s, e; 

    // 若无{,则s等于keylen
    for (s = 0; s < keylen; s++)
        // 遇到第一个{跳出
        if (key[s] == '{') break;


    // 若key中无{,则s等于keylen,整个key参与hash
    // 0x3FFF对应10进制为16383
    // 16383对应二进制为14个1
    // 按位与运算时只取crc16结果的低14位
    if (s == keylen) return crc16(key,keylen) & 0x3FFF;
    
    // 若key中有{,查看是否有}
    // 若key中无},则e等于keylen,整个key参与hash
    for (e = s+1; e < keylen; e++)
        // 遇到第一个}跳出
        if (key[e] == '}') break;
        
    // key中无},整个key参与hash
    // key中有},但{}之间为空,整个key参与hash
    if (e == keylen || e == s+1) return crc16(key,keylen) & 0x3FFF;

    // {}中间部分参与hash
    // key+s+1 指针操作,向右移动s+1
    // e-s-1为{}中间字符串的长度
    return crc16(key+s+1,e-s-1) & 0x3FFF;
}

如果有多个花括号,从左向右,取第一个花括号中的内容进行hash。

缺陷

将redis集群退化成了单节点