DataStax Bulk Loader系列教程共分为六篇,这是此系列的最后一篇,本教程到此篇为止也将告一段落。很多时候我们会想要从其它地方向DataStax Enterprise (DSE)中加载数据,此篇文章中我们将给出相关的案例。
另外,我们也建议您在使用dsbulk时参考dsbulk 文档页面,从而了解所有的相关参数和选项。
范例30:从另一个DSE集群中加载数据
一个常见的情景就是将数据从一个DSE集群中移到另一个集群,dsbulk没有“迁移”功能,但是我们可以通过原生的装载卸载功能达到目的。一种方式是先将集群中的数据卸载到本地文件系统,然后再将这些数据装载到另一个集群:
$ dsbulk unload -h localhost -k dsbulkblog -t iris_with_id -url /tmp/dsbulkblog/migrate$ dsbulk load -h localhost -k dsbulkblog -t iris_with_id -url /tmp/dsbulkblog/migrate
这里的一个窍门是我们可以一次性将dsbulk unload to dsbulk load的结果通过Linux管道输出:
$ dsbulk unload -h localhost -k dsbulkblog -t iris_with_id | dsbulk load -h localhost -k dsbulkblog -t iris_with_id
这样就得到以下输出结果:
Operation directory: /tmp/logs/LOAD_20190314-172058-173447. Operation directory: /tmp/logs/UNLOAD_20190314-172058-192179. total | failed | rows/s | mb/s | kb/row | p50 ms | p99ms | p999ms 150 | 0 | 302 | 0.01 | 0.04 | 20.12 | 20.19 | 20.19 Operation UNLOAD_20190314-172058-192179 completed successfully in 0 seconds. total | failed | rows/s | mb/s | kb/row | p50 ms | p99ms | p999ms | batches 150 | 0 | 52 | 0.00 | 0.04 | 20.94 | 60.29 | 61.34 | 1.00O peration LOAD_20190314-172058-173447 completed successfully in 2 seconds. Last processed positions can be found in positions.txt
虽然第二种方法挺巧妙的,但是我们必须要点出这个方法的一个弊端。这里面的卸载和装载都是单线程的,因为他们都是通过标准输入/标准输出 (stdout/stdin)来完成的。两步走的方式更为稳妥且两步之间互不干扰,但是你将不得不先完成所有的卸载,然后才能进行装载。
范例30.1:保留存活时间(TTLs)和时间戳的数据迁移
有的时候我们希望在迁移数据时保留写入时间(writetime)和存活时间(TTL),我们可以通过dsbulk和自定义的CQL查询语句达到目的。首先,我们在卸载数据时需要保留数据的写入时间和存活时间:
$ dsbulk unload -h localhost -query "SELECT id, petal_length, WRITETIME(petal_length) AS w_petal_length, TTL(petal_length) AS l_petal_length, petal_width, WRITETIME(petal_width) AS w_petal_width, TTL(petal_width) AS l_petal_width, sepal_length, WRITETIME(sepal_length) AS w_sepal_length, TTL(sepal_length) AS l_sepal_length, sepal_width, WRITETIME(sepal_width) AS w_sepal_width, TTL(sepal_width) AS l_sepal_width, species, WRITETIME(species) AS w_species, TTL(species) AS l_species FROM dsbulkblog.iris_with_id" -url /tmp/dsbulkblog/migrate
下一步是装载数据。我们将通过批量语句(batch statements)完成这一步,原因是对于每一个INSERT语句,我们只能设置一个写入时间和存活时间。
所以我们需要对每一个常规字段(petal_length, petal_width, sepal_length, sepal_width, and species)都用一个INSERT语句。
我们将会把这些INSERT语句都放入同一个批处理(batch)中并对应同一个分区键(即id),这样这些语句就会在Cassandra中被视为同一批改变(mutation)并在执行时保证原子性。
$ dsbulk load -h localhost -query "BEGIN BATCH INSERT INTO dsbulkblog.iris_with_id(id, petal_length) VALUES (:id, :petal_length)USING TIMESTAMP :w_petal_length AND TTL :l_petal_length; INSERT INTO dsbulkblog.iris_with_id(id, petal_width) VALUES (:id, :petal_width)USING TIMESTAMP :w_petal_width AND TTL :l_petal_width; INSERT INTO dsbulkblog.iris_with_id(id, sepal_length) VALUES (:id, :sepal_length)USING TIMESTAMP :w_sepal_length AND TTL :l_sepal_length; INSERT INTO dsbulkblog.iris_with_id(id, sepal_width) VALUES (:id, :sepal_width)USING TIMESTAMP :w_sepal_width AND TTL :l_sepal_width; INSERT INTO dsbulkblog.iris_with_id(id, species) VALUES (:id, :species)USING TIMESTAMP :w_species AND TTL :l_species; APPLY BATCH;" -url /tmp/dsbulkblog/migrate --batch.mode DISABLED
范例30.2:在同一集群中迁移数据
上述范例同样可用于源集群和目标集群是同一集群的情况。一个典型的情况就是如果你想要改变一个已经存有数据的表的模式(schema),你就可以借鉴上述方案。
虽然CQL支持添加或删除常规字段且很容易就能做到,但是CQL不支持改变主键(包括分区键partition keys和聚类列clustering columns)。想要做到这点,你需要复制数据——然而CQL也不支持数据复制。
比如,让我们改变我们前面用的iris数据的schema,让species这个字段变成分区键,然后让ID这个字段变成聚类列。我们可以通过CQL实现:
$ cqlsh -e "CREATE TABLE dsbulkblog.iris_by_species(id INT, petal_length DOUBLE, petal_width DOUBLE, sepal_length DOUBLE, sepal_width DOUBLE, species TEXT, PRIMARY KEY ((species), id));"
到这一步,我们可以从iris_with_id这个表卸载数据,然后再将这些数据装载到叫iris_by_species的表:
$ dsbulk unload -h localhost -k dsbulkblog -t iris_with_id | dsbulk load -h localhost -k dsbulkblog -t iris_by_species
我们可以通过对比dsbulk count的结果来抽查数据迁移的成果:
$ dsbulk count -k dsbulkblog -t iris_with_id -stats global --log.verbosity 0150$ dsbulk count -k dsbulkblog -t iris_by_species -stats global --log.verbosity 0150
范例31:从DSEFS装载数据
一个常见的用例就是考虑如何从DSEFS(DataStax Enterprise默认的分布式文件系统)装载数据。
dsbulk没有从DSEFS URL装载数据的原生功能,但是我们有几种方式可以搞定这个问题。为了演示方便,让我们在一个Analytics开启(意味着DSEFS开启)的集群中放入一些数据:
$ dse fs "mkdir dsefs:///dsbulkblog"$ dse fs "cp file:///tmp/dsbulkblog/iris.csv dsefs:///dsbulkblog/"
我们可以通过下面的命令看到数据已经被存入集群了:
$ dse fs "cat dsefs:///dsbulkblog/iris.csv"
然后我们可以用同样的命令将这些数据导入dsbulk:
$ dse fs "cat dsefs:///dsbulkblog/iris.csv" | dsbulk load -k dsbulkblog -t iris_with_id
我们也可以用针对DSEFS的WebHDFS达成同样的效果:
$ dsbulk load -k dsbulkblog -t iris_with_id -url http://localhost:5598/webhdfs/v1/dsbulkblog/iris.csv?op=OPEN
范例32:从MySQL装载数据
利用同样的思路,我们也可以从关系型数据库向DSE迁移数据——即综合使用关系型数据库的命令行,先向它的标准输出(stdout)写入数据,再将数据导入dsbulk。以MySQL为例,你可能需要这么操作(提示:MySQL的输出会以制表键为分隔符):
$ mysql --user=mysqluser --password=mypassword -B --execute="SELECT id, petal_length, petal_width, sepal_length, sepal_width, species FROM mydb.iris_with_id" | dsbulk load -k dsbulkblog -t iris_with_id -delim " " -header false -m "id,petal_length,petal_width,sepal_length,sepal_width,species"