1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        ES不香嗎,為啥還要ClickHouse?

        共 13980字,需瀏覽 28分鐘

         ·

        2021-07-17 10:17


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



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


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


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


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


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


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

        ElasticSearch 是為分布式設計的,有很好的擴展性,在一個典型的分布式配置中,每一個節(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(關系 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 服務容器和一個 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:把原始消息復制一份,這樣抽取的信息同時可以保留原始消息。

        • 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 對應為字段為空值。


        正則表達式查詢,查詢匹配某個正則表達式的數(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"

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

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

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


        我們畫出出所有的查詢的響應時間的分布:

        總查詢時間的對比如下:

        通過測試數(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,這也解釋了為什么用很多的公司應從 ES 切換到 Clickhouse 之上。


        作者:Gang Tao

        編輯: 51CTO技術棧  | 陶家龍

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


        推薦閱讀:

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

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

        企業(yè)IT技術架構(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
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

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

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            啊啊啊轻点视频 | 深夜福利视频网址 | 亚洲加勒比在线 | 天堂成人网站 | 亚洲AV无码精品成人影院麻豆 | 性爱AV网 | 国产标清视频 | 4438国产精品一区二区 | 国产又粗又硬又长又爽的 | 亚洲天堂影院 |