<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ES不香嗎,為啥還要ClickHouse?

          共 13980字,需瀏覽 28分鐘

           ·

          2021-07-17 10:17


          Elasticsearch 是一個實時的分布式搜索分析引擎,它的底層是構(gòu)建在 Lucene 之上的。簡單來說是通過擴展 Lucene 的搜索能力,使其具有分布式的功能。



          ES 通常會和其它兩個開源組件 Logstash(日志采集)和 Kibana(儀表盤)一起提供端到端的日志/搜索分析的功能,常常被簡稱為 ELK。


          Clickhouse 是俄羅斯搜索巨頭 Yandex 開發(fā)的面向列式存儲的關(guān)系型數(shù)據(jù)庫。ClickHouse 是過去兩年中 OLAP 領(lǐng)域中最熱門的,并于 2016 年開源。


          ES 是最為流行的大數(shù)據(jù)日志和搜索解決方案,但是近幾年來,它的江湖地位受到了一些挑戰(zhàn),許多公司已經(jīng)開始把自己的日志解決方案從 ES 遷移到了 Clickhouse,這里就包括:攜程,快手等公司。


          架構(gòu)和設(shè)計的對比


          ES 的底層是 Lucenc,主要是要解決搜索的問題。搜索是大數(shù)據(jù)領(lǐng)域要解決的一個常見的問題,就是在海量的數(shù)據(jù)量要如何按照條件找到需要的數(shù)據(jù)。搜索的核心技術(shù)是倒排索引和布隆過濾器。


          ES 通過分布式技術(shù),利用分片與副本機制,直接解決了集群下搜索性能與高可用的問題。

          ElasticSearch 是為分布式設(shè)計的,有很好的擴展性,在一個典型的分布式配置中,每一個節(jié)點(node)可以配制成不同的角色。

          如上圖所示:

          • Client Node,負責 API 和數(shù)據(jù)的訪問的節(jié)點,不存儲/處理數(shù)據(jù)。

          • Data Node,負責數(shù)據(jù)的存儲和索引。

          • Master Node,管理節(jié)點,負責 Cluster 中的節(jié)點的協(xié)調(diào),不存儲數(shù)據(jù)。


          ClickHouse 是基于 MPP 架構(gòu)的分布式 ROLAP(關(guān)系 OLAP)分析引擎。每個節(jié)點都有同等的責任,并負責部分數(shù)據(jù)處理(不共享任何內(nèi)容)。


          ClickHouse 是一個真正的列式數(shù)據(jù)庫管理系統(tǒng)(DBMS)。在 ClickHouse 中,數(shù)據(jù)始終是按列存儲的,包括矢量(向量或列塊)執(zhí)行的過程。


          讓查詢變得更快,最簡單且有效的方法是減少數(shù)據(jù)掃描范圍和數(shù)據(jù)傳輸時的大小,而列式存儲和數(shù)據(jù)壓縮就可以幫助實現(xiàn)上述兩點。


          Clickhouse 同時使用了日志合并樹,稀疏索引和 CPU 功能(如 SIMD 單指令多數(shù)據(jù))充分發(fā)揮了硬件優(yōu)勢,可實現(xiàn)高效的計算。


          Clickhouse 使用 Zookeeper 進行分布式節(jié)點之間的協(xié)調(diào)。

          為了支持搜索,Clickhouse 同樣支持布隆過濾器。


          查詢對比實戰(zhàn)


          為了對比 ES 和 Clickhouse 的基本查詢能力的差異,我寫了一些代碼來驗證:
          https://github.com/gangtao/esvsch

          這個測試的架構(gòu)如下:

          架構(gòu)主要有四個部分組成:


          ①ES stack


          ES stack 有一個單節(jié)點的 Elastic 的容器和一個 Kibana 容器組成,Elastic 是被測目標之一,Kibana 作為驗證和輔助工具。


          部署代碼如下:
          version: '3.7'

          services:
            elasticsearch:
              image: docker.elastic.co/elasticsearch/elasticsearch:7.4.0
              container_name: elasticsearch
              environment:
                - xpack.security.enabled=false
                - discovery.type=single-node
              ulimits:
                memlock:
                  soft: -1
                  hard: -1
                nofile:
                  soft: 65536
                  hard: 65536
              cap_add:
                - IPC_LOCK
              volumes:
                - elasticsearch-data:/usr/share/elasticsearch/data
              ports:
                - 9200:9200
                - 9300:9300
              deploy:
                resources:
                  limits:
                    cpus: '4'
                    memory: 4096M
                  reservations:
                    memory: 4096M

            kibana:
              container_name: kibana
              image: docker.elastic.co/kibana/kibana:7.4.0
              environment:
                - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
              ports:
                - 5601:5601
              depends_on:
                - elasticsearch

          volumes:
            elasticsearch-data:
              driver: local

          ②Clickhouse stack


          Clickhouse stack 有一個單節(jié)點的 Clickhouse 服務(wù)容器和一個 TabixUI 作為 Clickhouse 的客戶端。


          部署代碼如下:
          version: "3.7"
          services:
            clickhouse:
              container_name: clickhouse
              image: yandex/clickhouse-server
              volumes:
                - ./data/config:/var/lib/clickhouse
              ports:
                - "8123:8123"
                - "9000:9000"
                - "9009:9009"
                - "9004:9004"
              ulimits:
                nproc: 65535
                nofile:
                  soft: 262144
                  hard: 262144
              healthcheck:
                test: ["CMD""wget""--spider""-q""localhost:8123/ping"]
                interval: 30s
                timeout: 5s
                retries: 3
              deploy:
                resources:
                  limits:
                    cpus: '4'
                    memory: 4096M
                  reservations:
                    memory: 4096M

            tabixui:
              container_name: tabixui
              image: spoonest/clickhouse-tabix-web-client
              environment:
                - CH_NAME=dev
                - CH_HOST=127.0.0.1:8123
                - CH_LOGIN=default
              ports:
                - "18080:80"
              depends_on:
                - clickhouse
              deploy:
                resources:
                  limits:
                    cpus: '0.1'
                    memory: 128M
                  reservations:
                    memory: 128M

          ③數(shù)據(jù)導入 stack


          數(shù)據(jù)導入部分使用了 Vector.dev 開發(fā)的 vector,該工具和 fluentd 類似,都可以實現(xiàn)數(shù)據(jù)管道式的靈活的數(shù)據(jù)導入。


          ④測試控制 stack


          測試控制我使用了 Jupyter,使用了 ES 和 Clickhouse 的 Python SDK 來進行查詢的測試。


          用 Docker compose 啟動 ES 和 Clickhouse 的 stack 后,我們需要導入數(shù)據(jù),我們利用 Vector 的 generator 功能,生成 syslog,并同時導入 ES 和 Clickhouse。


          在這之前,我們需要在 Clickhouse 上創(chuàng)建表。ES 的索引沒有固定模式,所以不需要事先創(chuàng)建索引。


          創(chuàng)建表的代碼如下:
          CREATE TABLE default.syslog(
              application String,
              hostname String,
              message String,
              mid String,
              pid String,
              priority Int16,
              raw String,
              timestamp DateTime('UTC'),
              version Int16
          ENGINE = MergeTree()
              PARTITION BY toYYYYMMDD(timestamp)
              ORDER BY timestamp
              TTL timestamp + toIntervalMonth(1);

          創(chuàng)建好表之后,我們就可以啟動 vector,向兩個 stack 寫入數(shù)據(jù)了。vector 的數(shù)據(jù)流水線的定義如下:
          [sources.in]
            type = "generator"
            format = "syslog"
            interval = 0.01
            count = 100000

          [transforms.clone_message]
            type = "add_fields"
            inputs = ["in"]
            fields.raw = "{{ message }}"

          [transforms.parser]
            # General
            type = "regex_parser"
            inputs = ["clone_message"]
            field = "message" # optional, default
            patterns = ['^<(?P<priority>\d*)>(?P<version>\d) (?P<timestamp>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z) (?P<hostname>\w+\.\w+) (?P<application>\w+) (?P<pid>\d+) (?P<mid>ID\d+) - (?P<message>.*)$']

          [transforms.coercer]
            type = "coercer"
            inputs = ["parser"]
            types.timestamp = "timestamp"
            types.version = "int"
            types.priority = "int"

          [sinks.out_console]
            # General
            type = "console"
            inputs = ["coercer"
            target = "stdout" 

            # Encoding
            encoding.codec = "json" 


          [sinks.out_clickhouse]
            host = "http://host.docker.internal:8123"
            inputs = ["coercer"]
            table = "syslog"
            type = "clickhouse"

            encoding.only_fields = ["application""hostname""message""mid""pid""priority""raw""timestamp""version"]
            encoding.timestamp_format = "unix"

          [sinks.out_es]
            # General
            type = "elasticsearch"
            inputs = ["coercer"]
            compression = "none" 
            endpoint = "http://host.docker.internal:9200" 
            index = "syslog-%F"

            # Encoding

            # Healthcheck
            healthcheck.enabled = true

          這里簡單介紹一下這個流水線:

          • source.in:生成 syslog 的模擬數(shù)據(jù),生成 10w 條,生成間隔和 0.01 秒。

          • transforms.clone_message:把原始消息復(fù)制一份,這樣抽取的信息同時可以保留原始消息。

          • transforms.parser:使用正則表達式,按照 syslog 的定義,抽取出 application,hostname,message,mid,pid,priority,timestamp,version 這幾個字段。

          • transforms.coercer:數(shù)據(jù)類型轉(zhuǎn)化。

          • sinks.out_console:把生成的數(shù)據(jù)打印到控制臺,供開發(fā)調(diào)試。

          • sinks.out_clickhouse:把生成的數(shù)據(jù)發(fā)送到Clickhouse。

          • sinks.out_es:把生成的數(shù)據(jù)發(fā)送到 ES。


          運行 Docker 命令,執(zhí)行該流水線:
          docker run \
                  -v $(mkfile_path)/vector.toml:/etc/vector/vector.toml:ro \
                  -p 18383:8383 \
                  timberio/vector:nightly-alpine

          數(shù)據(jù)導入后,我們針對一下的查詢來做一個對比。ES 使用自己的查詢語言來進行查詢,Clickhouse 支持 SQL,我簡單測試了一些常見的查詢,并對它們的功能和性能做一些比較。


          返回所有的記錄:
          # ES
          {
            "query":{
              "match_all":{}
            }
          }

          # Clickhouse 
          "SELECT * FROM syslog"

          匹配單個字段:
          # ES
          {
            "query":{
              "match":{
                "hostname":"for.org"
              }
            }
          }

          # Clickhouse 
          "SELECT * FROM syslog WHERE hostname='for.org'"

          匹配多個字段:
          # ES
          {
            "query":{
              "multi_match":{
                "query":"up.com ahmadajmi",
                  "fields":[
                    "hostname",
                    "application"
                  ]
              }
            }
          }

          # Clickhouse、
          "SELECT * FROM syslog WHERE hostname='for.org' OR application='ahmadajmi'"

          單詞查找,查找包含特定單詞的字段:
          # ES
          {
            "query":{
              "term":{
                "message":"pretty"
              }
            }
          }

          # Clickhouse
          "SELECT * FROM syslog WHERE lowerUTF8(raw) LIKE '%pretty%'"

          范圍查詢,查找版本大于 2 的記錄:
          # ES
          {
            "query":{
              "range":{
                "version":{
                  "gte":2
                }
              }
            }
          }

          # Clickhouse
          "SELECT * FROM syslog WHERE version >= 2"

          查找到存在某字段的記錄:
          # ES
          {
            "query":{
              "exists":{
                "field":"application"
              }
            }
          }

          # Clickhouse
          "SELECT * FROM syslog WHERE application is not NULL"

          ES 是文檔類型的數(shù)據(jù)庫,每一個文檔的模式不固定,所以會存在某字段不存在的情況;而 Clickhouse 對應(yīng)為字段為空值。


          正則表達式查詢,查詢匹配某個正則表達式的數(shù)據(jù):
          # ES
          {
            "query":{
              "regexp":{
                "hostname":{
                  "value":"up.*",
                    "flags":"ALL",
                      "max_determinized_states":10000,
                        "rewrite":"constant_score"
                }
              }
            }
          }

          # Clickhouse
          "SELECT * FROM syslog WHERE match(hostname, 'up.*')"

          聚合計數(shù),統(tǒng)計某個字段出現(xiàn)的次數(shù):
          # ES
          {
            "aggs":{
              "version_count":{
                "value_count":{
                  "field":"version"
                }
              }
            }
          }

          # Clickhouse
          "SELECT count(version) FROM syslog"

          聚合不重復(fù)的值,查找所有不重復(fù)的字段的個數(shù):
          # ES
          {
            "aggs":{
              "my-agg-name":{
                "cardinality":{
                  "field":"priority"
                }
              }
            }
          }

          # Clickhouse
          "SELECT count(distinct(priority)) FROM syslog "

          我用 Python 的 SDK,對上述的查詢在兩個 Stack 上各跑 10 次,然后統(tǒng)計查詢的性能結(jié)果。


          我們畫出出所有的查詢的響應(yīng)時間的分布:

          總查詢時間的對比如下:

          通過測試數(shù)據(jù)我們可以看出 Clickhouse 在大部分的查詢的性能上都明顯要優(yōu)于 Elastic。


          在正則查詢(Regex query)和單詞查詢(Term query)等搜索常見的場景下,也并不遜色。


          在聚合場景下,Clickhouse 表現(xiàn)異常優(yōu)秀,充分發(fā)揮了列村引擎的優(yōu)勢。


          注意,我的測試并沒有任何優(yōu)化,對于 Clickhouse 也沒有打開布隆過濾器??梢?Clickhouse 確實是一款非常優(yōu)秀的數(shù)據(jù)庫,可以用于某些搜索的場景。


          當然 ES 還支持非常豐富的查詢功能,這里只有一些非常基本的查詢,有些查詢可能存在無法用 SQL 表達的情況。


          總結(jié)


          本文通過對于一些基本查詢的測試,對比了 Clickhouse 和 Elasticsearch 的功能和性能。


          測試結(jié)果表明,Clickhouse 在這些基本場景表現(xiàn)非常優(yōu)秀,性能優(yōu)于 ES,這也解釋了為什么用很多的公司應(yīng)從 ES 切換到 Clickhouse 之上。


          作者:Gang Tao

          編輯: 51CTO技術(shù)棧  | 陶家龍

          出處:zhuanlan.zhihu.com/p/353296392


          推薦閱讀:

          世界的真實格局分析,地球人類社會底層運行原理

          不是你需要中臺,而是一名合格的架構(gòu)師(附各大廠中臺建設(shè)PPT)

          企業(yè)IT技術(shù)架構(gòu)規(guī)劃方案

          論數(shù)字化轉(zhuǎn)型——轉(zhuǎn)什么,如何轉(zhuǎn)?

          企業(yè)10大管理流程圖,數(shù)字化轉(zhuǎn)型從業(yè)者必備!

          【中臺實踐】華為大數(shù)據(jù)中臺架構(gòu)分享.pdf

          華為的數(shù)字化轉(zhuǎn)型方法論

          華為如何實施數(shù)字化轉(zhuǎn)型(附PPT)

          超詳細280頁Docker實戰(zhàn)文檔!開放下載

          華為大數(shù)據(jù)解決方案(PPT)


          瀏覽 77
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本逼逼网 | 亚洲无码高清视频在线 | 国内毛片毛片毛片毛片 | 中日韩欧美一级A片免费 | 婷婷色一二三区波多野结衣 |