记一次亿级表的分表实践

1、背景

系统中有一张交易记录表,从系统商用到现在,尽管MySQL单表数据已经累计到一亿,但是基于72核CPU和384G内存的配置,导也是相安无事。不过防患于未然,运维向我们提出了整改的要求,并限制单表数据不超过2000万。

2、分表方案

业务上这张表只会根据userId进行查询,对此我们决定采取水平分表的方案,目前单表总共一亿的数据,并且每个月产生1000万的增量数据。
在此我们要算出满足未来三年数据量增长的总表数。
12kw*3+10kw=46kw,46kw/2kw=23,为了有更多的容错空间,我们最终确定分为30张表,从tabale01-table30。
初步讨论对userId取模来确定对应分表,但是这里存在两个问题
1.userId并不是连续不断的数字,对其取余会出现分配不均的情况
2.如果数据增长太快,超出预计,就需要再添加分表,取模的值发生改变,所有的数据都需要重新迁移到分表中,工作量太大。

3、一致性Hash算法

就有大神给我们提出办法,让我们使用一致性Hash算法进行分表,就能解决以上的问题,那什么是一致性Hash算法呢?

一致性hash:对节点和数据,都做一次hash运算,然后比较节点和数据的hash值,数据值和节点最相近的节点作为处理节点。为了分布得更均匀,通过使用虚拟节点的方式,每个节点计算出n个hash值,均匀地放在hash环上这样数据就能比较均匀地分布到每个节点。

(1)环形Hash空间
这里有一个叫一致性Hash环的数据结构,环的起点是0,终点是2^32 - 1,并且首尾相连,环的中间的整数按逆时针分布,这个环的整数分布范围是[0, 2^32-1]。如下图:
Hash环
(2)对表名进行Hash获取对应key并映射到Hash环上,相同的对象Hash值是一致的,如下图:
Hash表名
(3)对userId进行Hash获取对应key并映射到Hash环上,如下图:
Hash用户Id
(4)然后Hash(userId)的key以顺时针方向计算,得到与Hash(分表名)的key最近的节点对应的分表名,如下图:
寻找对应分表
经过以上的四个步骤完成了一致性Hash算法,得到userId对应的分表。

4、一致性Hash算法Java实现

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 一致性Hash算法
 *
 * @param <T> 节点类型
 */
public class ConsistentHash<T> {
   
    /**
     * 复制的节点个数
     */
    private final int numberOfReplicas;
    /**
     * 一致性Hash环
     */
    private final SortedMap<Long, T> circle = new TreeMap<>();
    /**
     * Hash计算对象,用于自定义hash算法
     */
    HashFunction hashFunction;

    /**
     * 构造,使用Java默认的Hash算法
     *
     * @param numberOfReplicas 复制的节点个数,增加每个节点的复制节点有利于负载均衡
     * @param nodes            节点对象
     */
    public ConsistentHash(int numberOfReplicas, Collection<T> nodes) {
   
        this.numberOfReplicas = numberOfReplicas;
        this.hashFunction = new HashFunction() {
   

            @Override
            public Long hash(Object key) {
   
                //return fnv1HashingAlg(key.toString());
                return md5HashingAlg(key.toString());
            }
        };
        //初始化节点
        for (T node : nodes) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值