ClickHouse介绍

  • ClickHouse是俄罗斯搜索引擎Yandex开发的一个高性能列式数据库系统,支持SQL查询,具有高并发、高可靠、高扩展性等特点
  • Java连接ClickHouse有以下几种方式
  • 1、使用JDBC连接:ClickHouse提供了JDBC驱动,可以使用JDBC API连接到ClickHouse,类似于连接其他关系型数据库。可以使用Java中JDBC APIClickHouse进行操作,例如执行SQL查询、插入、更新、删除等操作。连接方式如下:
Class.forName("ru.yandex.clickhouse.ClickHouseDriver");
Connection conn = DriverManager.getConnection("jdbc:clickhouse://localhost:8123/test","default","");
  • 2、使用ClickHouse-Java客户端连接:ClickHouse-Java是一个基于HTTP协议的ClickHouse客户端,具有跨平台、跨语言、易于使用等特点。可以使用Java代码通过ClickHouse-Java连接到ClickHouse并执行查询、插入、更新、删除等操作。连接方式如下:
ClickHouseDataSource dataSource = new ClickHouseDataSource("jdbc:clickhouse://localhost:8123/test");
  • 3、使用ORM框架连接:如果使用的Java应用涉及数据存储的逻辑比较复杂,可以使用ORM框架连接到ClickHouse,例如HibernateMyBatis等。ORM框架会自动将Java对象映射到ClickHouse中的表结构,简化了代码编写和维护。ORM框架连接方式和其他数据库连接方式类似,需要根据具体框架进行配置和使用。
  • 我们使用clickhouse作为大数据组件,存储前端设备实时采集到的海量数据,用做大数据的存储和分析

问题介绍

  • 我们使用Java语言开发,连接数据库保存数据,实时分批写入
  • 我们程序使用的是clickhousejdbc驱动方式,maven依赖如下:
	    <!-- clickhouse 相关依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.5</version>
        </dependency>
        <dependency>
            <groupId>ru.yandex.clickhouse</groupId>
            <artifactId>clickhouse-jdbc</artifactId>
            <version>0.2.6</version>
        </dependency>
        <!-- clickhouse end -->
  • 一开始使用时,未发现超时问题,后面连接上比较多的雷达设备后,数据量写入压力大增,写入报错,连接超时
  • 使用DruidDataSource建立连接,连接里已经设置了超时时间
	@Bean(name = "clickHouseDataSource")
    @ConditionalOnProperty(prefix = "spring.datasource.click-house",name = "url")
    public DataSource clickHouseDataSource() {
        DruidDataSource datasource = new DruidDataSource();
        datasource.setUrl(url);
        datasource.setDriverClassName(driverClassName);
        datasource.setInitialSize(initialSize);
        datasource.setMinIdle(minIdle);
        datasource.setMaxActive(maxActive);
        datasource.setMaxWait(maxWait);
        datasource.setUsername(username);
        datasource.setPassword(password);
        Properties properties = new Properties();
        properties.put("socket_timeout", timeout);
        datasource.setConnectProperties(properties);
        return datasource;
    }
  • clickkouse保存失败,报错信息截取如下
Caused by: ru.yandex.clickhouse.except.ClickHouseUnknownException: ClickHouse exception, 
code: 1002, host: 192.168.1.100, port: 8123; failed to respond
  • 关键报错截取为code 1002, 8123 failed to respon,报错信息也很明显,就是连接超时
  • 使用数据库工具测试数据库是否可以连接,发现clickhouse仍然是可以连接的,服务正常
  • 此时,问题已经很明显了,这个就是Java程序连接clickhouse的超时问题

解决写入超时

  • 数据库连接超时,是偶现现象。数据库与程序都在一个网络环境内,网络连接应该是没问题的
  • 连接超时,有可能是程序的写入或查询数据量过大,数据库未在限定时间范围内返回结果,程序认定超时,抛出报错
  • 程序连接的代码已经设置了超时时间,还是报了这个错误,找其他原因
  • 最终发现还需要修改clickhouse数据库设置,就是clickhouse服务端的参数配置
  • 修改clickhouse配置文件,/etc/clickhouse-serverconfig.xmlkeep_alive_timeout参数,默认是3,可以改为60s
    <!-- For 'Connection: keep-alive' in HTTP 1.1 -->
    <keep_alive_timeout>3</keep_alive_timeout>
  • 重启clickhouse服务(systemctl restart clickhouse-server),问题解决
  • 对于写入压力的问题,除了修改超时时间,也要减少写入次数,clickhouse是允许一批写入大量数据的
  • 我们的做法是,使用kafka作为数据来源于clickhouse的中间装置,kafka接收数据后,在一定条件(一定毫秒数或一定数据量)后,作为一批数据,批量发送给clickhouse的写入程序,批量写入
  • 有兴趣的小伙伴可以参考我这篇博客:Spring-kafka配置参数详解,消息批量发送与批量接收消费
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐