【转载】ClickHouse缩减shard数量

ClickHouse缩减shard数量

 2019-10-14   |    0 评论   |    881 浏览

背景

我手里目前有一个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数据

1

2

3

4

5

6

7

8

rsync -avzH --port=873 --delete --progress --exclude=system --password-file=/etc/rsyncd.passwd [email protected]::ftp /data2/clickhouse/data

 

[[email protected] clickhouse]# rsync -avzH --port=873 --delete --progress --password-file=/etc/rsyncd.passwd [email protected]::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

1

ALTER TABLE db.table ATTACH PART 'part'

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

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

1

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

代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

# -*- 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)