优秀的编程知识分享平台

网站首页 > 技术文章 正文

C# 字符串作为分表取模几种方式(c#字符串列表)

nanyue 2024-08-13 08:11:27 技术文章 12 ℃

在现今数据体量越来越大的时代,分库分表已经成为应对各种瓶颈的常用手段。当然已有不少数据库已经原生支持分库分表,如MongoDB的分片、PostgresSQL的分表等等;虽然提供了很强大的功能,但是也存在着各种限制或者不足。

在数据体量还没达到一定量级,仅仅需要简单的分表即可满足性能要求,但使用如MongoDB集群又存在成本高问题时,有没有简单并且可高度自定义的方案呢?比如使用客户编码(字符串类型)来分64张或128表并实现自动落入分表的方案。

分64张或128张表,64、128这都是数字,字符串又如何跟这些数字关联起来,并且是稳定的关联关系。那就是今天的主题:字符串作为分表取模几种方式 !

NO.1 通过加密类计算哈希值转成Int64的数值,然后根据具体分表数取余。

通过MD5计算:

public int GetModByMD5(string customerNo)
{
      using (var md5 = MD5.Create())
       {
           byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(customerNo));
           int number = BitConverter.ToInt64(hashBytes, 0);
          /*一般情况下,仅有相同字符串才能计算出相等的number
            但number取余后,数值范围是0~123
          */
           renturn number%128;
       }
}

通过SHA256计算:

public int GetModBySHA256(string customerNo)
{
      using (var sHA256 = SHA256.Create())
       {
           byte[] hashBytes = sHA256.ComputeHash(Encoding.UTF8.GetBytes(customerNo));
           int number = BitConverter.ToInt64(hashBytes, 0);
          /*一般情况下,仅有相同字符串才能计算出相等的number
            但number取余后,数值范围是0~123
          */
           renturn number%128;
       }
}

还有很多中加密类计算哈希值的方式这里不就一一列出。

NO.2 通过字符串的Unicode编码进行计算。

public int GetModByUnicode(string customerNo)
{
    long number=0;
    foreach (char c in customerNo)
    {
          number += (int)c;   //可以改为乘等累计
    }
    /*
      使用Unicode编码,字符串中字符一样(与顺序无关)的计算出的结果完成一样
      如CT01001和CT00011,计算出的number均是393
    */
      renturn number%128;
}

计算出每个客户编码对应的Mod后,可以根据此值找到数据库命名关系对应的表,如订单表命名格式:order_{mod},即:order_0...order_123;

说明:使用这种简单计算取模的方式,存在着数据分布不均的可能,如某些大体量的客户都落在了同一张或几张表,导致一些表的数据特别多,这种情况会降低分表策略旨在提升的性能效果。为了应对这一问题,需要根据实际业务和数据特征,采取更为精细和动态的数据分布策略。

注:为什么不直接使用拓展方法GetHashCode()呢,虽然使用GetHashCode()扩展方法也能计算出简便的散列值;但此方法计算的值与运行环境有密切关联,仅在同一个程序且没有重启的情况下,计算的结果才是一致的,然而一旦程序重启,原有的散列值计算就会发生变化,不存在稳定关联关系。

最近发表
标签列表