点击教程

从本教程中可以期待什么?

通过本教程,您将学习如何设置一个简单的ClickHouse集群。 它会很小,但却是容错和可扩展的。 然后,我们将使用其中一个示例数据集来填充数据并执行一些演示查询。

单节点设置

为了推迟分布式环境的复杂性,我们将首先在单个服务器或虚拟机上部署ClickHouse。 ClickHouse通常是从debrpm 包安装,但对于不支持它们的操作系统也有 替代方法

例如,您选择了从 deb 包安装,执行:

  1. sudo apt-get install apt-transport-https ca-certificates dirmngr
  2. sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv E0C56BD4
  3. echo "deb https://repo.clickhouse.tech/deb/stable/ main/" | sudo tee \
  4. /etc/apt/sources.list.d/clickhouse.list
  5. sudo apt-get update
  6. sudo apt-get install -y clickhouse-server clickhouse-client
  7. sudo service clickhouse-server start
  8. clickhouse-client

在我们安装的软件中包含这些包:

  • clickhouse-client 包,包含 clickhouse-client 应用程序,它是交互式ClickHouse控制台客户端。
  • clickhouse-common 包,包含一个ClickHouse可执行文件。
  • clickhouse-server 包,包含要作为服务端运行的ClickHouse配置文件。

服务端配置文件位于 /etc/clickhouse-server/。 在进一步讨论之前,请注意 config.xml文件中的<path> 元素. Path决定了数据存储的位置,因此该位置应该位于磁盘容量较大的卷上;默认值为 /var/lib/clickhouse/。 如果你想调整配置,考虑到它可能会在未来的软件包更新中被重写,直接编辑config.xml 文件并不方便。 推荐的方法是在配置文件目录创建文件,作为config.xml文件的“补丁”,用以复写配置元素。

你可能已经注意到了, clickhouse-server 安装后不会自动启动。 它也不会在更新后自动重新启动。 您启动服务端的方式取决于您的初始系统,通常情况下是这样:

  1. sudo service clickhouse-server start

  1. sudo /etc/init.d/clickhouse-server start

服务端日志的默认位置是 /var/log/clickhouse-server/。当服务端在日志中记录 Ready for connections 消息,即表示服务端已准备好处理客户端连接。

一旦 clickhouse-server 启动并运行,我们可以利用 clickhouse-client 连接到服务端,并运行一些测试查询,如 SELECT "Hello, world!";.

Clickhouse-client的快速提示

交互模式:

  1. clickhouse-client
  2. clickhouse-client --host=... --port=... --user=... --password=...

启用多行查询:

  1. clickhouse-client -m
  2. clickhouse-client --multiline

以批处理模式运行查询:

  1. clickhouse-client --query='SELECT 1'
  2. echo 'SELECT 1' | clickhouse-client
  3. clickhouse-client <<< 'SELECT 1'

从指定格式的文件中插入数据:

  1. clickhouse-client --query='INSERT INTO table VALUES' < data.txt
  2. clickhouse-client --query='INSERT INTO table FORMAT TabSeparated' < data.tsv

导入示例数据集

现在是时候用一些示例数据填充我们的ClickHouse服务器。 在本教程中,我们将使用Yandex的匿名数据。Metrica,在成为开源之前以生产方式运行ClickHouse的第一个服务(更多关于这一点 历史科). 有 多种导入Yandex的方式。梅里卡数据集,为了本教程,我们将使用最现实的一个。

下载并提取表数据

  1. curl https://clickhouse-datasets.s3.yandex.net/hits/tsv/hits_v1.tsv.xz | unxz --threads=`nproc` > hits_v1.tsv
  2. curl https://clickhouse-datasets.s3.yandex.net/visits/tsv/visits_v1.tsv.xz | unxz --threads=`nproc` > visits_v1.tsv

提取的文件大小约为10GB。

创建表

与大多数数据库管理系统一样,ClickHouse在逻辑上将表分组为 “databases”. 有一个 default 数据库,但我们将创建一个名为新的 tutorial:

  1. clickhouse-client --query "CREATE DATABASE IF NOT EXISTS tutorial"

与数据库相比,创建表的语法要复杂得多(请参阅 参考资料. 一般 CREATE TABLE 声明必须指定三个关键的事情:

  1. 要创建的表的名称。
  2. Table schema, i.e. list of columns and their 数据类型.
  3. 表引擎 及其设置,这决定了如何物理执行对此表的查询的所有细节。

YandexMetrica是一个网络分析服务,样本数据集不包括其全部功能,因此只有两个表可以创建:

  • hits 是一个表格,其中包含所有用户在服务所涵盖的所有网站上完成的每个操作。
  • visits 是一个包含预先构建的会话而不是单个操作的表。

让我们看看并执行这些表的实际创建表查询:

  1. CREATE TABLE tutorial.hits_v1
  2. (
  3. `WatchID` UInt64,
  4. `JavaEnable` UInt8,
  5. `Title` String,
  6. `GoodEvent` Int16,
  7. `EventTime` DateTime,
  8. `EventDate` Date,
  9. `CounterID` UInt32,
  10. `ClientIP` UInt32,
  11. `ClientIP6` FixedString(16),
  12. `RegionID` UInt32,
  13. `UserID` UInt64,
  14. `CounterClass` Int8,
  15. `OS` UInt8,
  16. `UserAgent` UInt8,
  17. `URL` String,
  18. `Referer` String,
  19. `URLDomain` String,
  20. `RefererDomain` String,
  21. `Refresh` UInt8,
  22. `IsRobot` UInt8,
  23. `RefererCategories` Array(UInt16),
  24. `URLCategories` Array(UInt16),
  25. `URLRegions` Array(UInt32),
  26. `RefererRegions` Array(UInt32),
  27. `ResolutionWidth` UInt16,
  28. `ResolutionHeight` UInt16,
  29. `ResolutionDepth` UInt8,
  30. `FlashMajor` UInt8,
  31. `FlashMinor` UInt8,
  32. `FlashMinor2` String,
  33. `NetMajor` UInt8,
  34. `NetMinor` UInt8,
  35. `UserAgentMajor` UInt16,
  36. `UserAgentMinor` FixedString(2),
  37. `CookieEnable` UInt8,
  38. `JavascriptEnable` UInt8,
  39. `IsMobile` UInt8,
  40. `MobilePhone` UInt8,
  41. `MobilePhoneModel` String,
  42. `Params` String,
  43. `IPNetworkID` UInt32,
  44. `TraficSourceID` Int8,
  45. `SearchEngineID` UInt16,
  46. `SearchPhrase` String,
  47. `AdvEngineID` UInt8,
  48. `IsArtifical` UInt8,
  49. `WindowClientWidth` UInt16,
  50. `WindowClientHeight` UInt16,
  51. `ClientTimeZone` Int16,
  52. `ClientEventTime` DateTime,
  53. `SilverlightVersion1` UInt8,
  54. `SilverlightVersion2` UInt8,
  55. `SilverlightVersion3` UInt32,
  56. `SilverlightVersion4` UInt16,
  57. `PageCharset` String,
  58. `CodeVersion` UInt32,
  59. `IsLink` UInt8,
  60. `IsDownload` UInt8,
  61. `IsNotBounce` UInt8,
  62. `FUniqID` UInt64,
  63. `HID` UInt32,
  64. `IsOldCounter` UInt8,
  65. `IsEvent` UInt8,
  66. `IsParameter` UInt8,
  67. `DontCountHits` UInt8,
  68. `WithHash` UInt8,
  69. `HitColor` FixedString(1),
  70. `UTCEventTime` DateTime,
  71. `Age` UInt8,
  72. `Sex` UInt8,
  73. `Income` UInt8,
  74. `Interests` UInt16,
  75. `Robotness` UInt8,
  76. `GeneralInterests` Array(UInt16),
  77. `RemoteIP` UInt32,
  78. `RemoteIP6` FixedString(16),
  79. `WindowName` Int32,
  80. `OpenerName` Int32,
  81. `HistoryLength` Int16,
  82. `BrowserLanguage` FixedString(2),
  83. `BrowserCountry` FixedString(2),
  84. `SocialNetwork` String,
  85. `SocialAction` String,
  86. `HTTPError` UInt16,
  87. `SendTiming` Int32,
  88. `DNSTiming` Int32,
  89. `ConnectTiming` Int32,
  90. `ResponseStartTiming` Int32,
  91. `ResponseEndTiming` Int32,
  92. `FetchTiming` Int32,
  93. `RedirectTiming` Int32,
  94. `DOMInteractiveTiming` Int32,
  95. `DOMContentLoadedTiming` Int32,
  96. `DOMCompleteTiming` Int32,
  97. `LoadEventStartTiming` Int32,
  98. `LoadEventEndTiming` Int32,
  99. `NSToDOMContentLoadedTiming` Int32,
  100. `FirstPaintTiming` Int32,
  101. `RedirectCount` Int8,
  102. `SocialSourceNetworkID` UInt8,
  103. `SocialSourcePage` String,
  104. `ParamPrice` Int64,
  105. `ParamOrderID` String,
  106. `ParamCurrency` FixedString(3),
  107. `ParamCurrencyID` UInt16,
  108. `GoalsReached` Array(UInt32),
  109. `OpenstatServiceName` String,
  110. `OpenstatCampaignID` String,
  111. `OpenstatAdID` String,
  112. `OpenstatSourceID` String,
  113. `UTMSource` String,
  114. `UTMMedium` String,
  115. `UTMCampaign` String,
  116. `UTMContent` String,
  117. `UTMTerm` String,
  118. `FromTag` String,
  119. `HasGCLID` UInt8,
  120. `RefererHash` UInt64,
  121. `URLHash` UInt64,
  122. `CLID` UInt32,
  123. `YCLID` UInt64,
  124. `ShareService` String,
  125. `ShareURL` String,
  126. `ShareTitle` String,
  127. `ParsedParams` Nested(
  128. Key1 String,
  129. Key2 String,
  130. Key3 String,
  131. Key4 String,
  132. Key5 String,
  133. ValueDouble Float64),
  134. `IslandID` FixedString(16),
  135. `RequestNum` UInt32,
  136. `RequestTry` UInt8
  137. )
  138. ENGINE = MergeTree()
  139. PARTITION BY toYYYYMM(EventDate)
  140. ORDER BY (CounterID, EventDate, intHash32(UserID))
  141. SAMPLE BY intHash32(UserID)
  142. SETTINGS index_granularity = 8192
  1. CREATE TABLE tutorial.visits_v1
  2. (
  3. `CounterID` UInt32,
  4. `StartDate` Date,
  5. `Sign` Int8,
  6. `IsNew` UInt8,
  7. `VisitID` UInt64,
  8. `UserID` UInt64,
  9. `StartTime` DateTime,
  10. `Duration` UInt32,
  11. `UTCStartTime` DateTime,
  12. `PageViews` Int32,
  13. `Hits` Int32,
  14. `IsBounce` UInt8,
  15. `Referer` String,
  16. `StartURL` String,
  17. `RefererDomain` String,
  18. `StartURLDomain` String,
  19. `EndURL` String,
  20. `LinkURL` String,
  21. `IsDownload` UInt8,
  22. `TraficSourceID` Int8,
  23. `SearchEngineID` UInt16,
  24. `SearchPhrase` String,
  25. `AdvEngineID` UInt8,
  26. `PlaceID` Int32,
  27. `RefererCategories` Array(UInt16),
  28. `URLCategories` Array(UInt16),
  29. `URLRegions` Array(UInt32),
  30. `RefererRegions` Array(UInt32),
  31. `IsYandex` UInt8,
  32. `GoalReachesDepth` Int32,
  33. `GoalReachesURL` Int32,
  34. `GoalReachesAny` Int32,
  35. `SocialSourceNetworkID` UInt8,
  36. `SocialSourcePage` String,
  37. `MobilePhoneModel` String,
  38. `ClientEventTime` DateTime,
  39. `RegionID` UInt32,
  40. `ClientIP` UInt32,
  41. `ClientIP6` FixedString(16),
  42. `RemoteIP` UInt32,
  43. `RemoteIP6` FixedString(16),
  44. `IPNetworkID` UInt32,
  45. `SilverlightVersion3` UInt32,
  46. `CodeVersion` UInt32,
  47. `ResolutionWidth` UInt16,
  48. `ResolutionHeight` UInt16,
  49. `UserAgentMajor` UInt16,
  50. `UserAgentMinor` UInt16,
  51. `WindowClientWidth` UInt16,
  52. `WindowClientHeight` UInt16,
  53. `SilverlightVersion2` UInt8,
  54. `SilverlightVersion4` UInt16,
  55. `FlashVersion3` UInt16,
  56. `FlashVersion4` UInt16,
  57. `ClientTimeZone` Int16,
  58. `OS` UInt8,
  59. `UserAgent` UInt8,
  60. `ResolutionDepth` UInt8,
  61. `FlashMajor` UInt8,
  62. `FlashMinor` UInt8,
  63. `NetMajor` UInt8,
  64. `NetMinor` UInt8,
  65. `MobilePhone` UInt8,
  66. `SilverlightVersion1` UInt8,
  67. `Age` UInt8,
  68. `Sex` UInt8,
  69. `Income` UInt8,
  70. `JavaEnable` UInt8,
  71. `CookieEnable` UInt8,
  72. `JavascriptEnable` UInt8,
  73. `IsMobile` UInt8,
  74. `BrowserLanguage` UInt16,
  75. `BrowserCountry` UInt16,
  76. `Interests` UInt16,
  77. `Robotness` UInt8,
  78. `GeneralInterests` Array(UInt16),
  79. `Params` Array(String),
  80. `Goals` Nested(
  81. ID UInt32,
  82. Serial UInt32,
  83. EventTime DateTime,
  84. Price Int64,
  85. OrderID String,
  86. CurrencyID UInt32),
  87. `WatchIDs` Array(UInt64),
  88. `ParamSumPrice` Int64,
  89. `ParamCurrency` FixedString(3),
  90. `ParamCurrencyID` UInt16,
  91. `ClickLogID` UInt64,
  92. `ClickEventID` Int32,
  93. `ClickGoodEvent` Int32,
  94. `ClickEventTime` DateTime,
  95. `ClickPriorityID` Int32,
  96. `ClickPhraseID` Int32,
  97. `ClickPageID` Int32,
  98. `ClickPlaceID` Int32,
  99. `ClickTypeID` Int32,
  100. `ClickResourceID` Int32,
  101. `ClickCost` UInt32,
  102. `ClickClientIP` UInt32,
  103. `ClickDomainID` UInt32,
  104. `ClickURL` String,
  105. `ClickAttempt` UInt8,
  106. `ClickOrderID` UInt32,
  107. `ClickBannerID` UInt32,
  108. `ClickMarketCategoryID` UInt32,
  109. `ClickMarketPP` UInt32,
  110. `ClickMarketCategoryName` String,
  111. `ClickMarketPPName` String,
  112. `ClickAWAPSCampaignName` String,
  113. `ClickPageName` String,
  114. `ClickTargetType` UInt16,
  115. `ClickTargetPhraseID` UInt64,
  116. `ClickContextType` UInt8,
  117. `ClickSelectType` Int8,
  118. `ClickOptions` String,
  119. `ClickGroupBannerID` Int32,
  120. `OpenstatServiceName` String,
  121. `OpenstatCampaignID` String,
  122. `OpenstatAdID` String,
  123. `OpenstatSourceID` String,
  124. `UTMSource` String,
  125. `UTMMedium` String,
  126. `UTMCampaign` String,
  127. `UTMContent` String,
  128. `UTMTerm` String,
  129. `FromTag` String,
  130. `HasGCLID` UInt8,
  131. `FirstVisit` DateTime,
  132. `PredLastVisit` Date,
  133. `LastVisit` Date,
  134. `TotalVisits` UInt32,
  135. `TraficSource` Nested(
  136. ID Int8,
  137. SearchEngineID UInt16,
  138. AdvEngineID UInt8,
  139. PlaceID UInt16,
  140. SocialSourceNetworkID UInt8,
  141. Domain String,
  142. SearchPhrase String,
  143. SocialSourcePage String),
  144. `Attendance` FixedString(16),
  145. `CLID` UInt32,
  146. `YCLID` UInt64,
  147. `NormalizedRefererHash` UInt64,
  148. `SearchPhraseHash` UInt64,
  149. `RefererDomainHash` UInt64,
  150. `NormalizedStartURLHash` UInt64,
  151. `StartURLDomainHash` UInt64,
  152. `NormalizedEndURLHash` UInt64,
  153. `TopLevelDomain` UInt64,
  154. `URLScheme` UInt64,
  155. `OpenstatServiceNameHash` UInt64,
  156. `OpenstatCampaignIDHash` UInt64,
  157. `OpenstatAdIDHash` UInt64,
  158. `OpenstatSourceIDHash` UInt64,
  159. `UTMSourceHash` UInt64,
  160. `UTMMediumHash` UInt64,
  161. `UTMCampaignHash` UInt64,
  162. `UTMContentHash` UInt64,
  163. `UTMTermHash` UInt64,
  164. `FromHash` UInt64,
  165. `WebVisorEnabled` UInt8,
  166. `WebVisorActivity` UInt32,
  167. `ParsedParams` Nested(
  168. Key1 String,
  169. Key2 String,
  170. Key3 String,
  171. Key4 String,
  172. Key5 String,
  173. ValueDouble Float64),
  174. `Market` Nested(
  175. Type UInt8,
  176. GoalID UInt32,
  177. OrderID String,
  178. OrderPrice Int64,
  179. PP UInt32,
  180. DirectPlaceID UInt32,
  181. DirectOrderID UInt32,
  182. DirectBannerID UInt32,
  183. GoodID String,
  184. GoodName String,
  185. GoodQuantity Int32,
  186. GoodPrice Int64),
  187. `IslandID` FixedString(16)
  188. )
  189. ENGINE = CollapsingMergeTree(Sign)
  190. PARTITION BY toYYYYMM(StartDate)
  191. ORDER BY (CounterID, StartDate, intHash32(UserID), VisitID)
  192. SAMPLE BY intHash32(UserID)
  193. SETTINGS index_granularity = 8192

您可以使用以下交互模式执行这些查询 clickhouse-client (只需在终端中启动它,而不需要提前指定查询)或尝试一些 替代接口 如果你愿意的话

正如我们所看到的, hits_v1 使用 基本MergeTree引擎,而 visits_v1 使用 崩溃 变体。

导入数据

数据导入到ClickHouse是通过以下方式完成的 INSERT INTO 查询像许多其他SQL数据库。 然而,数据通常是在一个提供 支持的序列化格式 而不是 VALUES 子句(也支持)。

我们之前下载的文件是以制表符分隔的格式,所以这里是如何通过控制台客户端导入它们:

  1. clickhouse-client --query "INSERT INTO tutorial.hits_v1 FORMAT TSV" --max_insert_block_size=100000 < hits_v1.tsv
  2. clickhouse-client --query "INSERT INTO tutorial.visits_v1 FORMAT TSV" --max_insert_block_size=100000 < visits_v1.tsv

ClickHouse有很多 要调整的设置 在控制台客户端中指定它们的一种方法是通过参数,我们可以看到 --max_insert_block_size. 找出可用的设置,它们意味着什么以及默认值的最简单方法是查询 system.settings 表:

  1. SELECT name, value, changed, description
  2. FROM system.settings
  3. WHERE name LIKE '%max_insert_b%'
  4. FORMAT TSV
  5. max_insert_block_size 1048576 0 "The maximum block size for insertion, if we control the creation of blocks for insertion."

您也可以 OPTIMIZE 导入后的表。 使用MergeTree-family引擎配置的表总是在后台合并数据部分以优化数据存储(或至少检查是否有意义)。 这些查询强制表引擎立即进行存储优化,而不是稍后进行一段时间:

  1. clickhouse-client --query "OPTIMIZE TABLE tutorial.hits_v1 FINAL"
  2. clickhouse-client --query "OPTIMIZE TABLE tutorial.visits_v1 FINAL"

这些查询开始一个I/O和CPU密集型操作,所以如果表一直接收到新数据,最好不要管它,让合并在后台运行。

现在我们可以检查表导入是否成功:

  1. clickhouse-client --query "SELECT COUNT(*) FROM tutorial.hits_v1"
  2. clickhouse-client --query "SELECT COUNT(*) FROM tutorial.visits_v1"

查询示例

  1. SELECT
  2. StartURL AS URL,
  3. AVG(Duration) AS AvgDuration
  4. FROM tutorial.visits_v1
  5. WHERE StartDate BETWEEN '2014-03-23' AND '2014-03-30'
  6. GROUP BY URL
  7. ORDER BY AvgDuration DESC
  8. LIMIT 10
  1. SELECT
  2. sum(Sign) AS visits,
  3. sumIf(Sign, has(Goals.ID, 1105530)) AS goal_visits,
  4. (100. * goal_visits) / visits AS goal_percent
  5. FROM tutorial.visits_v1
  6. WHERE (CounterID = 912887) AND (toYYYYMM(StartDate) = 201403) AND (domain(StartURL) = 'yandex.ru')

集群部署

ClickHouse集群是一个同质集群。 设置步骤:

  1. 在群集的所有计算机上安装ClickHouse服务器
  2. 在配置文件中设置群集配置
  3. 在每个实例上创建本地表
  4. 创建一个 分布式表

分布式表 实际上是一种 “view” 到ClickHouse集群的本地表。 从分布式表中选择查询使用集群所有分片的资源执行。 您可以为多个集群指定configs,并创建多个分布式表,为不同的集群提供视图。

具有三个分片的集群的示例配置,每个分片一个副本:

  1. <remote_servers>
  2. <perftest_3shards_1replicas>
  3. <shard>
  4. <replica>
  5. <host>example-perftest01j.yandex.ru</host>
  6. <port>9000</port>
  7. </replica>
  8. </shard>
  9. <shard>
  10. <replica>
  11. <host>example-perftest02j.yandex.ru</host>
  12. <port>9000</port>
  13. </replica>
  14. </shard>
  15. <shard>
  16. <replica>
  17. <host>example-perftest03j.yandex.ru</host>
  18. <port>9000</port>
  19. </replica>
  20. </shard>
  21. </perftest_3shards_1replicas>
  22. </remote_servers>

为了进一步演示,让我们创建一个新的本地表 CREATE TABLE 我们用于查询 hits_v1,但不同的表名:

  1. CREATE TABLE tutorial.hits_local (...) ENGINE = MergeTree() ...

创建提供集群本地表视图的分布式表:

  1. CREATE TABLE tutorial.hits_all AS tutorial.hits_local
  2. ENGINE = Distributed(perftest_3shards_1replicas, tutorial, hits_local, rand());

常见的做法是在集群的所有计算机上创建类似的分布式表。 它允许在群集的任何计算机上运行分布式查询。 还有一个替代选项可以使用以下方法为给定的SELECT查询创建临时分布式表 远程 表功能。

我们走吧 INSERT SELECT 将该表传播到多个服务器。

  1. INSERT INTO tutorial.hits_all SELECT * FROM tutorial.hits_v1;

碌莽禄Notice:

这种方法不适合大型表的分片。 有一个单独的工具 ツ环板-ョツ嘉ッツ偲 这可以重新分片任意大表。

正如您所期望的那样,如果计算量大的查询使用3台服务器而不是一个,则运行速度快N倍。

在这种情况下,我们使用了具有3个分片的集群,每个分片都包含一个副本。

为了在生产环境中提供弹性,我们建议每个分片应包含分布在多个可用区或数据中心(或至少机架)之间的2-3个副本。 请注意,ClickHouse支持无限数量的副本。

包含三个副本的一个分片集群的示例配置:

  1. <remote_servers>
  2. ...
  3. <perftest_1shards_3replicas>
  4. <shard>
  5. <replica>
  6. <host>example-perftest01j.yandex.ru</host>
  7. <port>9000</port>
  8. </replica>
  9. <replica>
  10. <host>example-perftest02j.yandex.ru</host>
  11. <port>9000</port>
  12. </replica>
  13. <replica>
  14. <host>example-perftest03j.yandex.ru</host>
  15. <port>9000</port>
  16. </replica>
  17. </shard>
  18. </perftest_1shards_3replicas>
  19. </remote_servers>

启用本机复制 动物园管理员 是必需的。 ClickHouse负责所有副本的数据一致性,并在失败后自动运行恢复过程。 建议将ZooKeeper集群部署在单独的服务器上(其中没有其他进程,包括ClickHouse正在运行)。

ZooKeeper不是一个严格的requirement:在某些简单的情况下,您可以通过将数据写入应用程序代码中的所有副本来复制数据。 这种方法是 建议,在这种情况下,ClickHouse将无法保证所有副本上的数据一致性。 因此,它成为您的应用程序的责任。

ZooKeeper位置在配置文件中指定:

  1. <zookeeper>
  2. <node>
  3. <host>zoo01.yandex.ru</host>
  4. <port>2181</port>
  5. </node>
  6. <node>
  7. <host>zoo02.yandex.ru</host>
  8. <port>2181</port>
  9. </node>
  10. <node>
  11. <host>zoo03.yandex.ru</host>
  12. <port>2181</port>
  13. </node>
  14. </zookeeper>

此外,我们需要设置宏来识别每个用于创建表的分片和副本:

  1. <macros>
  2. <shard>01</shard>
  3. <replica>01</replica>
  4. </macros>

如果在创建复制表时没有副本,则会实例化新的第一个副本。 如果已有实时副本,则新副本将克隆现有副本中的数据。 您可以选择首先创建所有复制的表,然后向其中插入数据。 另一种选择是创建一些副本,并在数据插入之后或期间添加其他副本。

  1. CREATE TABLE tutorial.hits_replica (...)
  2. ENGINE = ReplcatedMergeTree(
  3. '/clickhouse_perftest/tables/{shard}/hits',
  4. '{replica}'
  5. )
  6. ...

在这里,我们使用 ReplicatedMergeTree 表引擎。 在参数中,我们指定包含分片和副本标识符的ZooKeeper路径。

  1. INSERT INTO tutorial.hits_replica SELECT * FROM tutorial.hits_local;

复制在多主机模式下运行。 数据可以加载到任何副本中,然后系统会自动将其与其他实例同步。 复制是异步的,因此在给定时刻,并非所有副本都可能包含最近插入的数据。 至少应有一个副本允许数据摄取。 其他人将同步数据和修复一致性,一旦他们将再次变得活跃。 请注意,这种方法允许最近插入的数据丢失的可能性很低。

原始文章