ClickHouse要点小记

本文探讨了ClickHouse的分片、副本配置对性能的影响,强调了单分片多副本的选择原因,包括BI应用的量级、数据压缩、并发处理和JOIN性能。还提到了分区策略、副本同步机制、负载均衡方法,以及本地表与分布式表的优缺点对比,以及如何通过配置选择复制表以确保数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于分片,副本,节点

  • ck存在严格的限制,如果是单副本的情况下,停用一个分片会导致分布式表不可用
  • 4分片1副本需要4个ck节点,而3分片2副本需要6个CK节点,CK节点数为分片数乘副本数,不推荐一个节点上存在两个副本,若需要一节点两副本则新建两个数据库,动态传入数据库值
  • 节点扩容不会自动同步旧数据,有两种方式解决,以下两种方式均需要在新节点上重新创建表
    (1)创建一个新集群,select remote()函数查询A集群输入插入B集群,将原表重命名,在所有节点上建立与原表schema相同的新表,将实时数据写入新表,同时用clickhouse-copier工具将历史数据整体迁移到新表上来,再删除原表。当然在迁移期间,被重平衡的表是无法提供服务的,仍然不那么优雅。
    (2)调整weight权重,使数据前期优先存入新节点上,后续再重新调整weight。但是这会造成明显的热点问题,并且仅对直接写入分布式表才有效,并不可取。
    2021.2.22新增
    58采用的是单分片多副本,原因如下:https://xie.infoq.cn/article/ebfe0a6b0d6bdbbb4eae642ff
    • BI对接数仓应用层数据,总体来说量级较小,同时clickhouse有着高效的数据压缩比,采用单节点能存储当前BI的全量数据,且能满足未来几年的数据存储需求。
    • Clickhouse默认并发数为100,采用单分片每个节点都拥有全量数据,当qps过高时可横向增加节点来增大并发数。
    • clickhouse对Distributed 表的join支持较差,单分片不走网络,能提高join查询速度。

关于分区

那些有相同分区表达式值的数据片段才会合并。这意味着 你不应该用太精细的分区方案(超过一千个分区)。否则,会因为文件系统中的文件数量过多和需要打开的文件描述符过多,导致 SELECT 查询效率不佳。

关于副本同步机制

复制是多主异步的。
INSERT语句(以及ALTER)可在任意可用的服务器上执行。数据首先插入到本地的服务器 (即运行查询的服务器),然后数据被复制到其他服务器。

由于复制是异步的,所以最近插入的数据出现在其他副本上会有一定的延迟。

如果部分副本不可用,则在它们可用时写入数据。

如果副本可用, 则等待的时间是通过网络传输压缩数据块所耗费的时间。

默认情况下, INSERT操作只需等待一个副本写入成功后返回。如果仅将数据成功写入一个 副本,并且该副本的服务器不再存在, 则存储的数据将丢失。要启动来自多个副本的写入确 认机制,使用insert_quorum选项。

insert_quorum:启用仲裁写入,写入多少个副本才算成功。默认0。insert_quorum <2,则禁用仲裁写入;insert_quorum> = 2,则启用仲裁写入。
当在insert_quorum_timeout期间将数据正确写入副本的insert_quorum时,INSERT才能成功。如果由于任何原因而成功写入的副本数量未达到insert_quorum,则认为写入失败,并将从已写入数据的所有副本中删除插入的块。读取从insert_quorum写入的数据时,可以使用select_sequential_consistency选项。查询时可用副本的数量小于insert_quorum则会报错。
insert_quorum_timeout:仲裁写入超时(秒),默认60s。 如果超时时间内没有写完,则将生成一个异常,并且客户端必须重复查询才能将同一块写入相同或任何其他副本。

关于分布式表查询负载均衡调用副本

执行分布式查询时,首先计算分片的每个副本的错误数,然后将查询发送至最少错误的副本。如果没有错误或者错误数相同,则按如下的策略查询数据:
1.random(默认) : 将查询发送至任意一个副本。
2.nearest_hostname : 将查询发送至主机名最相似的副本。
3.in_order : 将查询按配置文件中的配置顺序发送至副本。
4.first_or_random : 选择第一个副本,如果第一个副本不可用,随机选择一个可用的副本。

关于建表

  1. 建表时添加on cluster 可以只操作一次在多个节点上同时新建本地表

关于分布式表

  • 直接在分布式表中插入数据数据落地规则:建分布式表时会有一个参数选择分片,一般是rand或者是hash,根据这个参数,还有weight权重 这两个属性,决定数据落地那个分片
  • 写数据到分布式表
    优点:clickhouse控制数据到分片的路由
    缺点:
    (1)数据是先写到一个分布式表的实例中并缓存起来,再逐渐分发到各个分片上去,实际是双写了数据(写入放大),浪费资源
    (2)数据写入默认是异步的,短时间内可能造成不一致
    (3)目标表中会产生较多的小parts,使merge(即compaction)过程压力增大
    相对而言,直接写本地表是同步操作,更快,parts的大小也比较合适,但是就要求应用层额外实现sharding和路由逻辑,如轮询或者随机等,在生产环境中推荐写本地表、读分布式表,可以引入第三方负载均衡工具,由第三方工具决定插入到那个表中,例如chproxy,或者Flink-ClickHouse Sink中实现随机路由,此处只是简单的随机分配,并未考虑集群负载占用的情况。https://www.jianshu.com/p/ab811cceb856
    2021.2.22新增
    • 负载均衡可以采用BalancedClickhouseDataSource轮询多个节点,druid已经有对应支持https://github.com/alibaba/druid/issues/3984使用简单;但是内部随机方式,可能会导致负载不均匀,虽然有定时检测机制,但是经测试,节点挂掉,请求直接报错;这种无法实现故障转移
    • nginx实现SLB,既可以轮询,也可以做故障转移,国内大厂采用此方案

      (1)没有配置副本,非复制表(MergeTree),每个节点为一个shard的情况:数据只被插入到一个本地表中。当一个节点挂了之后查询分布表会报错。
      ​ (2)配置副本,非复制表(MergeTree):数据只被插入到一个本地表中,虽然做了副本,但是MergeTree 引擎的表并不会自动复制数据,所有数据还是只在一个节点上。当一个节点挂了之后查询分布表不会报错,但是挂了的节点的数据会丢失。
      ​ (3)配置副本,复制表(ReplicatedMergeTree):插入到分布式表中的数据仅插入到其中一个本地表中,但通过复制机制传输到另一个节点的表中,因此两个本地表上的数据保持同步。一个节点挂了之后可以正常提供服务,查询分布式表不会报错,数据未丢失。
private Request buildRequest(ClickhouseRequestBlank requestBlank) {
        String resultCSV = String.join(" , ", requestBlank.getValues());
        String query = String.format("INSERT INTO %s VALUES %s", requestBlank.getTargetTable(), resultCSV);
        String host = sinkSettings.getClickhouseClusterSettings().getRandomHostUrl();

        BoundRequestBuilder builder = asyncHttpClient
                .preparePost(host)
                .setHeader(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=utf-8")
                .setBody(query);

        if (sinkSettings.getClickhouseClusterSettings().isAuthorizationRequired()) {
            builder.setHeader(HttpHeaders.Names.AUTHORIZATION, "Basic " + sinkSettings.getClickhouseClusterSettings().getCredentials());
        }

        return builder.build();
    }

    public String getRandomHostUrl() {
        currentHostId = ThreadLocalRandom.current().nextInt(hostsWithPorts.size());
        return hostsWithPorts.get(currentHostId);
    }

关于本地表引擎选择

  1. 推荐使用复制表而不是非复制表,普通mergetree会存在数据同步的问题,新建复制表时可以在配置文件中添加全局变量<macros>标签,指定分片名和副本名
  2. internal_replication参数 非复制表设置为false 复制表设置为true
    值为true则由表自动同步数据,若为false则由集群自动同步数据

关于集群监控

  1. 没有直接提供QPS等类似数据,需要根据日志计算
  2. 如果用grafana直连,指标高频查询会影响集群性能
  3. 如果采用clickhouse-exporter+prometheus+grafana的组合,prometheus监控flink会有小毛病

搭建的本地监控环境

Tabix用于查询sql,监控信息

http://172.16.10.128:8080/#!/login

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
Grafana专业监控

http://172.16.10.128:23000/login

账号密码均为admin
在这里插入图片描述
登入后进入此处可看到新建的三个仪表盘
在这里插入图片描述
Json标签号13606,模板地址https://grafana.com/grafana/dashboards/13606
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
Json标签号2515,模板地址https://grafana.com/grafana/dashboards/2515
在这里插入图片描述
在这里插入图片描述

### 使用 UniApp 开发小记账本应用程序 #### 项目概述 生活记账小程序通过前端 Vue 和 UniApp 设计开发,后端采用 SpringBoot 提供数据接口支持。主要功能模块包括首页展示、分类记账以及微信登录状态管理[^1]。 #### 创建新项目 首先安装 HBuilderX 或者其他 IDE 工具来创建一个新的 UniApp 项目: ```bash npm install -g @dcloudio/uni-cli uni create myAccountBookProject ``` 进入项目目录并初始化必要的配置文件。 #### 配置 App.vue 生命周期函数 为了更好地控制应用生命周期,在 `App.vue` 中定义如下几个重要钩子函数用于处理不同场景下的逻辑操作: - **onLaunch**: 当整个程序启动时调用此方法, 可以在这里做一些全局性的初始化工作. - **onShow**: 页面每次从前台切到后台再返回前台都会触发这个事件, 合适用来刷新某些实时变化的内容. - **onHide**: 对应于当用户点击 Home 键使 APP 进入后台运行模式时执行的动作. 这些设置有助于提升用户体验流畅度和响应速度[^2]. #### 数据绑定与交互实现 确保所有的业务逻辑都放置在 methods 下面,并且避免 data 属性名称同 method 名冲突以免造成不必要的错误;另外注意检查 HTML 标签内部是否存在重复属性声明尤其是集成第三方 UI 组件库 uView-ui 的时候要格外小心[^3]: ```html <template> <!-- 记录条目输入框 --> </template> <script> export default { name: 'RecordEntry', data() { return { recordType: '', amount: null, date: '' } }, methods:{ addNewRecord(){ // 添加新的财务记录... } } } </script> ``` #### 接口对接与缓存机制 对于前后端分离架构的应用来说,合理的 API 路由规划至关重要。这里推荐使用 RESTful 风格的服务端点配合 axios 发起 HTTP 请求完成增删改查等基本 CRUD 功能。与此同时引入 Redis 做为临时存储介质加速频繁访问的数据读取效率降低 MySQL 查询压力。 #### 微信开放能力接入 如果计划让这款理财工具具备社交分享特性,则需按照官方文档指引注册成为微信公众平台开发者账号获得 appid 权限认证之后才能正常使用诸如支付等功能服务。此外还可以考虑加入直播营销插件吸引更多潜在客户群体关注产品动态[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值