ClickHouse缩减shard数量

  |   0 评论   |   874 浏览

背景

我手里目前有一个4台服务器的小集群,每个节点上一个clickhouse-server实例。

最近打算开启双副本,有两种方案:

  1. 每个节点上启动2个实例

  2. 将shard数改为2个,凑成一个2shard双副本的集群

经过调研,以及和作者的交流,建议我们采用第2种方案

缩减shard步骤

整体步骤图

image.png

步骤

同步数据

我们需要将后两个节点作为前两个节点的副本存在,因此,需要将后两个节点上已有的数据添加到前两个节点中,因此,第一步就是同步数据,如下

shard3 --> shard1

shard4 --> shard2

同步方案可以使用rsync

停止shard3、shard4的服务

在shard3、shard4上搭建rsync服务

参考《使用rsync同步文件(service模式)

使用rsync同步ClickHouse数据

rsync -avzH --port=873 --delete --progress --exclude=system --password-file=/etc/rsyncd.passwd ch@192.168.31.4::ftp /data2/clickhouse/data

[root@cxy7.com clickhouse]# rsync -avzH --port=873 --delete --progress --password-file=/etc/rsyncd.passwd ch@192.168.31.4::ftp /data2/clickhouse/data
receiving incremental file list
created directory /data2/clickhouse/data
...
sent 832,491 bytes received 559,951,468 bytes 5,811,232.74 bytes/sec
total size is 1,121,177,109 speedup is 2.00


将数据添加至前两个节点

  1. 将parts数据移动到新的shard对应表的detached目录下

  2. ATTACH PART

ALTER TABLE db.table ATTACH PART 'part'

由于操作所有表比较繁琐,我写了一个脚本来搞,可以参考如下用法

可以使用migrate_parts.py迁移所有表的数据

python migrate_parts.py -s 192.168.31.4 -d 192.168.31.2 -D /data2/clickhouse/data

代码

# -*- coding: utf-8 -*-
import sys
import requests
import json
from urllib import quote
import os
from optparse import OptionParser
from optparse import OptionGroup

def run_cmd(host, query, port = 8123, database='cxy7_db'):
    url = 'http://%s:%d?user=%s&password=%s&database=%s&max_execution_time=300&query=' % (
    host, port, user, password, database)
    print query
    url += quote(query)
    resp = requests.post(url)
    print 'host------>%s' % host
    if resp.status_code == 200:
        return resp.content
    else:
        print 'err:', resp.content

if __name__ == "__main__":
    usage = "Usage: %prog [options] clickhouse python client"
    parser = OptionParser(usage=usage)
    ch_group = OptionGroup(parser, "cxy7.com clickhouse Config", "...")
    ch_group.add_option('-s', '--source', help='source server')
    ch_group.add_option('-d', '--dst', help='dst server')
    ch_group.add_option('-u', '--user', default = 'cxy7', help='user')
    ch_group.add_option('-p', '--password', default = 'cxy7_pwd', help='password')
    ch_group.add_option('-D', '--dir', help='data dir')

    parser.add_option_group(ch_group)

    options, args = parser.parse_args(sys.argv[1:])
    source = options.source
    dst = options.dst
    user = options.user
    password = options.password
    dir = options.dir

    if not source or not dst or not dir:
        print "field:(%s, %s, %s) can't be None" % (source, dst, dir)
        parser.print_help()
        sys.exit(-1)
    print 'migrate from %s to %s', source, dst

    sql = "SELECT database, table, name FROM system.parts WHERE active AND database != 'system' FORMAT JSON;"
    resp = run_cmd(source, sql)
    json = json.loads(resp)
    parts = json['data']
    ch_data = '/data1/clickhouse/data'
    for part in parts:
        database = part['database']
        table = part['table']
        part_name = part['name']
        part_path = dir + '/' + database + '/' + table + '/' + part_name
        detached_part_path = ch_data + '/' + database + '/' + table + '/detached/' + part_name
        print 'move:%s -> %s' % (part_path, detached_part_path)
        try:
           shutil.move(part_path, detached_part_path)
           cmd = 'chown -R clickhouse:clickhouse ' + detached_part_path
           os.system(cmd)
        except (IOError,AttributeError):
           print 'error'
           continue

        sql = "ALTER TABLE %s.%s ATTACH PART '%s'" % (database, table, part_name)
        print run_cmd(dst, sql)


读后有收获可以支付宝请作者喝咖啡