背景:

随着数据量的上升,OLAP一直是被讨论的话题,虽然druid,kylin能够解决OLAP问题,但是druid,kylin也是需要和hadoop全家桶一起用的,异常的笨重,再说我也搞不定,那只能找我能搞定的技术。故引进clickhoue,关于clickhoue在17年本人就开始关注,并且写了一些入门的介绍,直到19年clickhoue功能慢慢的丰富才又慢慢的关注,并且编写了同步程序,把mysql数据实时同步到clickhoue,并且最终在线上使用起来。

clickhouse面对海量数据,比如单表过百亿可以使用集群(复制+分片),如果数据量比较小,比如单表10-20亿使用单机就足以满足查询需求。如果使用复制需要使用zk,更多集群的请自行查阅官方资料。

单机部署(以前的文章也有写过单机部署) :

在2016年clickhouse刚开始开源的时候对Ubuntu支持非常友好,一个apt命令就可以安装了。对于centos等系统 支持就比较差,需要自己编译,而且不一定能够成功。随着使用人群的扩大,目前对于centos支持也是非常的友好 了,有rpm包可以直接安装。甚至目前Altinity公司已经制作了yum源,添加源之后直接yum安装完成。这个在官方 文档里面也有提到,参考: https://clickhouse.yandex/docs/en/getting_started/ https://github.com/Altinity/clickhouse-rpm-install 。目前线上使用的是centos 7.0的系统。之所以使用7.0的系统是因为同步数据的程序是用python写的,而且用到的 一个核心包:python-mysql-replication需要使用python 2.7的环境。同时由于clickhouse不兼容mysql协议,为了方便开发接入系统不用过多更改代码,引入了proxysql兼容mysql协议,clickhouse最新版本已经支持mysql协议,支持clickhouse的proxysql也需要python 2.7的环境,所以干脆直接用centos 7.0系统

测试环境:

服务器数量:1台

操作系统:centos 7.1

安装服务:clickhouse,mysql

安装mysql是测试clickhouse从mysql同步数据。

clickhouse安装:

添加yum源

curl -s https://packagecloud.io/install/repositories/altinity/clickhouse/script.rpm.sh | sudo bash

yum安装

yum install -y clickhouse-server clickhouse-client

服务启动

/etc/init.d/clickhouse-server start

默认数据存放位置是: /var/lib/clickhouse/

登录,查看数据库(默认用户是default,密码为空)

[root@ck-server-01 sync]# clickhouse-client -h 127.0.0.1ClickHouse client version19.9.2.4.

Connecting to127.0.0.1:9000as user default.

Connected to ClickHouse server version19.9.2 revision 54421.

ck-server-01:) show databases;

SHOW DATABASES

┌─name────┐

│ default │

│ system │

└─────────┘2 rows in set. Elapsed: 0.003sec.

ck-server-01 :)

default数据库里面没有任何东西,和mysql里面的test库是一样的。system库看名字就知道是什么。到这里clickhouse就部署完成,是不是很简单?

补充一点,在官方的文档里面有几点建议:

1. 关闭大页

2. 调整内存使用

3. 关闭cpu节能模式

echo 'performance' | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governorecho 0 > /proc/sys/vm/overcommit_memoryecho 'never' > /sys/kernel/mm/transparent_hugepage/enabled

mysql部署请自行部署。这里不做介绍。如果想从mysql同步数据那么binlog 格式必须是row。而且必须binlog_row_image=full

安装同步程序依赖的包;同步程序可以放在clickhouse服务器上面,也可以单独放在其他服务器。同步程序使用pypy启动,所以安装包的时候需要安装pyum -y install pypy-libs pypy pypy-devel

wget https://bootstrap.pypa.io/get-pip.py

pypy get-pip.py/usr/lib64/pypy-5.0.1/bin/pip install MySQL-python/usr/lib64/pypy-5.0.1/bin/pip install mysql-replication/usr/lib64/pypy-5.0.1/bin/pip install clickhouse-driver==0.0.20

/usr/lib64/pypy-5.0.1/bin/pip install redis

这里也安装了redis模块是因为同步的binlog pos可以存放在redis里面,当然程序也是支持存放在文件里面

proxysql安装(主要是为了clickhouse兼容mysql协议): proxysql在这里下载:https://github.com/sysown/proxysql/releases 选择带clickhouse的包下载,否则不会支持clickhouse。ps:较新版本的clickhouse已经原生兼容mysql协议。

proxysql安装及配置

rpm -ivh proxysql-2.0.3-1-clickhouse-centos7.x86_64.rpm

启动(必须这样启动,否则是不支持clickhouse的):

proxysql --clickhouse-server

登录proxysql,设置账户:

mysql -uadmin -padmin -h127.0.0.1 -P6032INSERT INTO clickhouse_users VALUES ('clicku','clickp',1,100);LOAD CLICKHOUSE USERS TORUNTIME;SAVE CLICKHOUSE USERS TO DISK;

使用proxysql连接到clickhouse:

[root@ck-server-01 sync]# mysql -u clicku -pclickp -h 127.0.0.1 -P6090

mysql: [Warning] Using a password on the command line interface can be insecure.

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connectionid is 28356Server version:5.5.30(ProxySQL ClickHouse Module)

Copyright (c)2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

Type'help;' or '\h' for help. Type '\c' to clearthe current input statement.

mysql>show databases;+---------+

| name |

+---------+

| default |

| system |

+---------+

mysql同步数据到clickhouse

mysql里面有个库yayun,库里面有张表tb1,同步这张表到clickhoue

mysql> useyayun;Databasechanged

mysql> show create tabletb1\G*************************** 1. row ***************************

Table: tb1Create Table: CREATE TABLE`tb1` (

`id`int(10) unsigned NOT NULLAUTO_INCREMENT,

`pay_money`decimal(20,2) NOT NULL DEFAULT '0.00',

`pay_day` dateNOT NULL,

`pay_time`datetime NOT NULL DEFAULT '0000-00-00 00:00:00',PRIMARY KEY(`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb41 row in set (0.00 sec)

1. clickhoue里面建库,建表。

ck-server-01 :) create databaseyayun;CREATE DATABASEyayun

Ok.0 rows in set. Elapsed: 0.021sec.

ck-server-01 :)

2. 建表(clickhouse建表的格式以及字段类型和mysql完全不一样,如果字段少还可以自己建,如果字段多比较痛苦,可以使用clickhouse自带的从mysql导数据的命令来建表),在建表之前需要进行授权,因为程序同步也是模拟一个从库拉取数据.

GRANT REPLICATION SLAVE, REPLICATION CLIENT, SELECT ON *.* TO 'ch_repl'@'127.0.0.1' identified by '123';

3. 登陆clickhouse进行建表

ck-server-01 :) useyayun;USEyayun

Ok.0 rows in set. Elapsed: 0.001sec.

ck-server-01 :) CREATE TABLEtb1

:-] ENGINE =MergeTree

:-] PARTITION BYtoYYYYMM(pay_time)

:-] ORDER BY (pay_time) AS:-] SELECT *:-] FROM mysql('127.0.0.1:3306', 'yayun', 'tb1', 'ch_repl', '123') ;CREATE TABLEtb1

ENGINE=MergeTree

PARTITIONBYtoYYYYMM(pay_time)ORDER BY pay_time AS

SELECT *

FROM mysql('127.0.0.1:3306', 'yayun', 'tb1', 'ch_repl', '123')

Ok.0 rows in set. Elapsed: 0.031 sec.

这里使用MergeTree引擎,MergeTree是clickhouse里面最牛逼的引擎,支持海量数据,支持索引,支持分区,支持更新删除。toYYYYMM(pay_time)的意思是根据pay_time分区,粒度是按月。ORDER BY (pay_time)的意思是根据pay_time排序存储,同时也是索引。上面的create table命令如果mysql表里面以后数据那么数据也会一并进入clickhouse里面。通常会limit 1,然后更改一下表结构。上面没有报错的话我们看看clickhouse里面的表结构:

ck-server-01 :) show create tabletb1;

SHOWCREATE TABLEtb1

┌─statement────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐

│CREATE TABLE yayun.tb1 (`id` UInt32, `pay_money` String, `pay_day` Date, `pay_time` DateTime) ENGINE = MergeTree PARTITION BY toYYYYMM(pay_time) ORDER BY pay_time SETTINGS index_granularity = 8192│

└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘1 rows in set. Elapsed: 0.002 sec.

其中这里的index_granularity = 8192是指索引的粒度。如果数据量没有达到百亿,那么通常无需更改。表结构也创建完成以后现在配置同步程序配置文件:metainfo.conf

[root@ck-server-01 sync]# catmetainfo.conf

# 从这里同步数据

[master_server]

host='127.0.0.1'port=3306user='ch_repl'

passwd='123'server_id=101# redis配置信息,用于存放pos点

[redis_server]

host='127.0.0.1'port=6379

passwd='12345'log_pos_prefix='log_pos_'#把log_position记录到文件

[log_position]file='./repl_pos.log'# ch server信息,数据同步以后写入这里

[clickhouse_server]

host=127.0.0.1port=9000

passwd=''user='default'#字段大小写. 1是大写,0是小写

column_lower_upper=0# 需要同步的数据库

[only_schemas]

schemas='yayun'# 需要同步的表

[only_tables]

tables='tb1'# 指定库表跳过DML语句(update,delete可选)

[skip_dmls_sing]

skip_delete_tb_name= ''skip_update_tb_name= ''#跳过所有表的DML语句(update,delete可选)

[skip_dmls_all]

#skip_type= 'delete'#skip_type= 'delete,update'skip_type= ''[bulk_insert_nums]

#多少记录提交一次

insert_nums=10#选择每隔多少秒同步一次,负数表示不启用,单位秒

interval=60# 同步失败告警收件人

[failure_alarm]

mail_host= 'xxx'mail_port= 25mail_user= 'xxx'mail_pass= 'xxx'mail_send_from= 'xxx'alarm_mail= 'xxx'#日志存放路径

[repl_log]

log_dir="/tmp/relication_mysql_clickhouse.log"

设置pos点:

和mysql搭建从库一样,配置从哪里开始同步,看mysql的pos点:

mysql>show master status;+------------------+----------+--------------+------------------+-------------------+

| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |

+------------------+----------+--------------+------------------+-------------------+

| mysql-bin.000069 | 4024404 | | | |

+------------------+----------+--------------+------------------+-------------------+

1 row in set (0.00 sec)

把pos点写入文件或者redis,我选择记录到文件就是。

[root@ck-server-01 sync]# catrepl_pos.log

[log_position]

filename= mysql-bin.000069position= 4024404[root@ck-server-01 sync]#

启动同步程序:

[root@ck-server-01 sync]# pypy mysql-clickhouse-replication.py --help

usage: Data Replication to clikhouse [-h] [-c CONF] [-d] [-l]

mysql data is copied to clikhouse

optional arguments:-h, --help show this help message and exit-c CONF, --conf CONF Data synchronization information file

-d, --debug Display SQL information-l, --logtoredis log position to redis ,default fileBy dengyayun @2019[root@ck-server-01 sync]#

默认pos点就是记录文件,无需再指定记录binlog pos方式

[root@ck-server-01 sync]# pypy mysql-clickhouse-replication.py --conf metainfo.conf --debug11:59:54 INFO 开始同步数据时间 2019-07-17 11:59:54

11:59:54 INFO 从服务器 127.0.0.1:3306同步数据11:59:54 INFO 读取binlog: mysql-bin.000069:4024404

11:59:54 INFO 同步到clickhouse server 127.0.0.1:9000

11:59:54 INFO 同步到clickhouse的数据库: ['yayun']11:59:54 INFO 同步到clickhouse的表: ['tb1']

mysql插入10条数据:

mysql> insert into tb1 (pay_money,pay_day,pay_time)values('66.22','2019-06-29','2019-06-29 14:00:00'),('66.22','2019-06-29','2019-06-29 14:00:00'),('66.22','2019-06-29','2019-06-29 14:00:00'),('66.22','2019-06-29','2019-06-29 14:00:00'),('66.22','2019-06-29','2019-06-29 14:00:00'),('66.22','2019-06-29','2019-06-29 14:00:00'),('66.22','2019-06-29','2019-06-29 14:00:00'),('66.22','2019-06-29','2019-06-29 14:00:00'),('66.22','2019-06-29','2019-06-29 14:00:00'),('66.22','2019-06-29','2019-06-29 14:00:00') ;

Query OK,10 rows affected (0.01sec)

Records:10 Duplicates: 0 Warnings: 0mysql> select * fromtb1;+----+-----------+------------+---------------------+

| id | pay_money | pay_day | pay_time |

+----+-----------+------------+---------------------+

| 1 | 66.22 | 2019-06-29 | 2019-06-29 14:00:00 |

| 3 | 66.22 | 2019-06-29 | 2019-06-29 14:00:00 |

| 5 | 66.22 | 2019-06-29 | 2019-06-29 14:00:00 |

| 7 | 66.22 | 2019-06-29 | 2019-06-29 14:00:00 |

| 9 | 66.22 | 2019-06-29 | 2019-06-29 14:00:00 |

| 11 | 66.22 | 2019-06-29 | 2019-06-29 14:00:00 |

| 13 | 66.22 | 2019-06-29 | 2019-06-29 14:00:00 |

| 15 | 66.22 | 2019-06-29 | 2019-06-29 14:00:00 |

| 17 | 66.22 | 2019-06-29 | 2019-06-29 14:00:00 |

| 19 | 66.22 | 2019-06-29 | 2019-06-29 14:00:00 |

同步程序日志输出:

[root@ck-server-01 sync]# pypy mysql-clickhouse-replication.py --conf metainfo.conf --debug12:12:09 INFO 开始同步数据时间 2019-07-17 12:12:09

12:12:09 INFO 从服务器 127.0.0.1:3306同步数据12:12:09 INFO 读取binlog: mysql-bin.000069:4024404

12:12:09 INFO 同步到clickhouse server 127.0.0.1:9000

12:12:09 INFO 同步到clickhouse的数据库: ['yayun']12:12:09 INFO 同步到clickhouse的表: ['tb1']12:12:09 INFO INSERT 数据插入SQL: INSERT INTO yayun.tb1 VALUES, [{u'id': 1, u'pay_money': '66.22', u'pay_day': datetime.date(2019, 6, 29), u'pay_time': datetime.datetime(2019, 6, 29, 14, 0)}, {u'id': 3, u'pay_money': '66.22', u'pay_day': datetime.date(2019, 6, 29), u'pay_time': datetime.datetime(2019, 6, 29, 14, 0)}, {u'id': 5, u'pay_money': '66.22', u'pay_day': datetime.date(2019, 6, 29), u'pay_time': datetime.datetime(2019, 6, 29, 14, 0)}, {u'id': 7, u'pay_money': '66.22', u'pay_day': datetime.date(2019, 6, 29), u'pay_time': datetime.datetime(2019, 6, 29, 14, 0)}, {u'id': 9, u'pay_money': '66.22', u'pay_day': datetime.date(2019, 6, 29), u'pay_time': datetime.datetime(2019, 6, 29, 14, 0)}, {u'id': 11, u'pay_money': '66.22', u'pay_day': datetime.date(2019, 6, 29), u'pay_time': datetime.datetime(2019, 6, 29, 14, 0)}, {u'id': 13, u'pay_money': '66.22', u'pay_day': datetime.date(2019, 6, 29), u'pay_time': datetime.datetime(2019, 6, 29, 14, 0)}, {u'id': 15, u'pay_money': '66.22', u'pay_day': datetime.date(2019, 6, 29), u'pay_time': datetime.datetime(2019, 6, 29, 14, 0)}, {u'id': 17, u'pay_money': '66.22', u'pay_day': datetime.date(2019, 6, 29), u'pay_time': datetime.datetime(2019, 6, 29, 14, 0)}, {u'id': 19, u'pay_money': '66.22', u'pay_day': datetime.date(2019, 6, 29), u'pay_time': datetime.datetime(2019, 6, 29, 14, 0)}]

clickhoue数据查询:

ck-server-01 :) select * fromtb1;SELECT *

FROMtb1

┌─id─┬─pay_money─┬────pay_day─┬────────────pay_time─┐

│1 │ 66.22 │ 2019-06-29 │ 2019-06-29 14:00:00│

│3 │ 66.22 │ 2019-06-29 │ 2019-06-29 14:00:00│

│5 │ 66.22 │ 2019-06-29 │ 2019-06-29 14:00:00│

│7 │ 66.22 │ 2019-06-29 │ 2019-06-29 14:00:00│

│9 │ 66.22 │ 2019-06-29 │ 2019-06-29 14:00:00│

│11 │ 66.22 │ 2019-06-29 │ 2019-06-29 14:00:00│

│13 │ 66.22 │ 2019-06-29 │ 2019-06-29 14:00:00│

│15 │ 66.22 │ 2019-06-29 │ 2019-06-29 14:00:00│

│17 │ 66.22 │ 2019-06-29 │ 2019-06-29 14:00:00│

│19 │ 66.22 │ 2019-06-29 │ 2019-06-29 14:00:00│

└────┴───────────┴────────────┴─────────────────────┘10 rows in set. Elapsed: 0.005 sec.

mysql数据更新:

mysql> update tb1 set pay_money='88.88';

Query OK,10 rows affected (0.00sec)

Rows matched:10 Changed: 10 Warnings: 0mysql> select * fromtb1;+----+-----------+------------+---------------------+

| id | pay_money | pay_day | pay_time |

+----+-----------+------------+---------------------+

| 1 | 88.88 | 2019-06-29 | 2019-06-29 14:00:00 |

| 3 | 88.88 | 2019-06-29 | 2019-06-29 14:00:00 |

| 5 | 88.88 | 2019-06-29 | 2019-06-29 14:00:00 |

| 7 | 88.88 | 2019-06-29 | 2019-06-29 14:00:00 |

| 9 | 88.88 | 2019-06-29 | 2019-06-29 14:00:00 |

| 11 | 88.88 | 2019-06-29 | 2019-06-29 14:00:00 |

| 13 | 88.88 | 2019-06-29 | 2019-06-29 14:00:00 |

| 15 | 88.88 | 2019-06-29 | 2019-06-29 14:00:00 |

| 17 | 88.88 | 2019-06-29 | 2019-06-29 14:00:00 |

| 19 | 88.88 | 2019-06-29 | 2019-06-29 14:00:00 |

+----+-----------+------------+---------------------+

10 rows in set (0.00 sec)

clickhoue数据查询:

ck-server-01 :) select * fromtb1;SELECT *

FROMtb1

┌─id─┬─pay_money─┬────pay_day─┬────────────pay_time─┐

│1 │ 88.88 │ 2019-06-29 │ 2019-06-29 14:00:00│

│3 │ 88.88 │ 2019-06-29 │ 2019-06-29 14:00:00│

│5 │ 88.88 │ 2019-06-29 │ 2019-06-29 14:00:00│

│7 │ 88.88 │ 2019-06-29 │ 2019-06-29 14:00:00│

│9 │ 88.88 │ 2019-06-29 │ 2019-06-29 14:00:00│

│11 │ 88.88 │ 2019-06-29 │ 2019-06-29 14:00:00│

│13 │ 88.88 │ 2019-06-29 │ 2019-06-29 14:00:00│

│15 │ 88.88 │ 2019-06-29 │ 2019-06-29 14:00:00│

│17 │ 88.88 │ 2019-06-29 │ 2019-06-29 14:00:00│

│19 │ 88.88 │ 2019-06-29 │ 2019-06-29 14:00:00│

└────┴───────────┴────────────┴─────────────────────┘10 rows in set. Elapsed: 0.009 sec.

可以看见数据都同步完成。

代码地址:

总结:

目前线上报表业务都已经在使用clickhoue,数据同步采用自行开发的同步程序进行同步。目前数据一致性没有什么问题。当然同步的表需要有自增主键,否则有些情况比较难处理。延时也比较小。数据的延时以及数据的一致性都有监控。

总体来说使用clickhoue处理olap还是非常不错的选择,小伙伴们可以尝试。

参考资料

clickhouse 同步mysql_ClickHouse单机部署以及从MySQL增量同步数据相关推荐

  1. Clickhouse单机部署以及从mysql增量同步数据

    背景: 随着数据量的上升,OLAP一直是被讨论的话题,虽然druid,kylin能够解决OLAP问题,但是druid,kylin也是需要和hadoop全家桶一起用的,我也搞不定,那只能找我能搞定的技术 ...

  2. 第02期:ClickHouse 单机部署以及从 MySQL 增量同步数据

    本期作者:邓亚运 37 互娱高级 DBA,负责公司 MySQL,Redis,Hadoop,Clickhouse 集群的管理和维护. 背景 随着数据量的上升,OLAP 一直是被讨论的话题,虽然 drui ...

  3. clickhouse 增量更新_Clickhouse單機部署以及從mysql增量同步數據

    背景: 隨着數據量的上升,OLAP一直是被討論的話題,雖然druid,kylin能夠解決OLAP問題,但是druid,kylin也是需要和hadoop全家桶一起用的,我也搞不定,那只能找我能搞定的技術 ...

  4. Kafka实现MySQL增量同步

    目标 本文是对[1]的复现和整理 环境 组件 版本 Zookeeper 3.6.0 Kafka 2.5.0 Mysql 8.0.21-0ubuntu0.20.04.4 准备工作 分别新建两个数据库A和 ...

  5. linux无法同步数据库表,Linux数据库:MySQL主从同步设置和同步错误处理

    注意: 1.两台服务器数据库版本应一致,如果不一致,从服务器的版本要高于主服务器的版本. 2.MySQL进行实时数据同步,本质上是将mysql动作同步到Slave服务器,而不是对实质的数据进行同 步. ...

  6. mysql增量同步kafka_canal解析mysql的binlog实时推送到kafka

    今天整理一下以前写的一个kafka消费canal的demo,实现实时推送数据到kafka.首先先介绍一下canal,官网是这么说的: 主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和 ...

  7. mysql增量同步kafka_MySQL数据实时增量同步到Kafka - Flume

    写在前面的话 需求,将MySQL里的数据实时增量同步到Kafka.接到活儿的时候,第一个想法就是通过读取MySQL的binlog日志,将数据写到Kafka.不过对比了一些工具,例如:Canel,Dat ...

  8. mysql 主从同步不一致_涨知识!MySQL 主从同步原理原来是这样的

    什么是 MySQL 主从同步 当 master(主)库的数据发生变化的时候,变化会实时的同步到slave(从)库. 主从同步有什么好处 水平扩展数据库的负载能力 容错,高可用.Failover/Hig ...

  9. mysql双击同步_求助,WINDOWS下MYSQL双机同步的问题

    展开全部 1.1 环境搭建 准备两台Windows NT 主机,分别安装好iKEY Server windows 版本,确定版本无误,确保e5a48de588b662616964757a6869646 ...

最新文章

  1. mysql中group_contact函数的使用
  2. javafx官方文档学习之二Scene体系学习一
  3. UA MATH564 概率论VI 数理统计基础5 F分布
  4. 从无到有算法养成篇:一文读懂有关Tree的前世今生
  5. Centos7 安装 Rabbitmq、Erlang
  6. python3 zip命令_zip错误:无效的命令参数(无法将zip文件写入终端)
  7. java除了框架还需要什么_除了框架,前端面试还问什么
  8. VALSE学习(九):物体检测进展
  9. 姿态传感器的原理与应用文献笔记
  10. 基于MFC的字符生产与旋转算法实现
  11. 头条python后台一面凉经
  12. PHP初级程序员出路
  13. 常用邮箱的 IMAP/POP3/SMTP 设置
  14. 江苏单招C语言试题,2011年对口单招计算机试卷(C语言+原理+电工答案).doc
  15. typora+阿里云图床+印象笔记+OneDrive安全保存你的文章
  16. 软件测试学习 之 Python 类属性 实例属性、实例方法 类方法 静态方法
  17. VScode 配置豆沙绿背景色(source insight同款背景色)
  18. 考驾照选择 AI 教练,心态稳定不会骂人
  19. Java 后端自学之路之小白
  20. 开发者十条途径【转】

热门文章

  1. R 语言载入包时不显示包的信息
  2. “华为云杯”2019人工智能创新应用大赛(图像分类比赛)总结记录
  3. 汇客huikeCRM项目实战-熟能生巧
  4. Python基础语法12 类的继承
  5. 搭建B2B2C多商户商城、分销系统的价值
  6. pdf如何转换成ppt格式?
  7. PhotoshopCS5 第三篇 创建选区
  8. 海尔linux系统密码,海尔路由器密码忘记了怎么办?
  9. windows DHCP服务器部署
  10. PreferenceManager Ver.0.1.4发布