ElasticSearch 高可用分布式集群搭建,与PHP多线程测试

方案:

  • 使用HAproxy:当其中一台ElasticSearch Master宕掉时,ElasticSearch集群会自动将运行正常的节点提升为Master,但HAproxy不会将失败的请求重新分发到新的Master Node
  • 使用ElasticSearch单search load balancer(外层负载均衡节点)双coordinator(调度节点)若干workhorse(数据节点)。先后在200并发Index、200并发Update测试下(跑在虚拟机下,线程太多就卡爆了),并前后分别测试了Down掉一台主coordinator、Down掉一台workhorse,都没有引起数据异常,集群工作正常

先贴一下使用HAproxy搭建集群失败的配置吧:

#全局配置
global
        daemon
        nbproc 4
        pidfile /tmp/haproxy.pid

#默认配置
defaults
        mode http               #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
        retries 2               #两次连接失败就认为是服务器不可用,也可以通过后面设置
        option redispatch           #当serverId对应的服务器挂掉后,强制定向到其他健康的服务器
        option httpclose            #HAProxy会针对客户端的第一条请求的返回添加cookie并返回给客户端,客户端发送后续请求时会发送此cookie到HAProxy
        #option abortonclose            #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
        maxconn 4096                #默认的最大连接数
        timeout connect 5000ms          #连接超时
        timeout client 30000ms          #客户端超时
        timeout server 30000ms          #服务器超时
        timeout check 2000          #心跳检测超时
        log 127.0.0.1 local0 err #[err warning info debug]

#统计页面配置
listen admin_stats
        bind 0.0.0.0:8888               #监听端口
        mode http                       #http的7层模式
        option httplog                  #采用http日志格式
        #log 127.0.0.1 local0 err
        maxconn 10
        stats refresh 30s               #统计页面自动刷新时间
        stats uri /                     #统计页面url
        stats realm XingCloud\ Haproxy  #统计页面密码框上提示文本
        stats auth admin:admin          #统计页面用户名和密码设置
        #stats hide-version             #隐藏统计页面上HAProxy的版本信息

#ElasticSearch Frontend
frontend eshttp
    bind 0.0.0.0:9200
    mode tcp
    use_backend eshttp_server

#ElasticSearch Backend
backend eshttp_server
    server eshttp1      vm12:9200 cookie 1 check inter 2000 rise 3 fall 3 weight 2
    server eshttp2      vm13:9200 cookie 2 check inter 2000 rise 3 fall 3 weight 1
    server eshttp3_bk   vm14:9200 cookie 3 check inter 1000 rise 3 fall 3 backup

采用ElasticSearch搭建集群的关键几个配置:

search load balancer(LB负载均衡节点):

cluster.name: harold                    #集群名称
node.name: "harold_lb"                  #节点名称

# 3. You want this node to be neither master nor data node, but
#    to act as a "search load balancer" (fetching data from nodes,
#    aggregating results, etc.)
#
node.master: false
node.data: false

discovery.zen.ping.unicast.hosts: ["vm11", "vm12", "vm13", "vm14", "vm15", "vm16"] #自动发现节点hosts

coordinator(Master调度节点):

cluster.name: harold                    #集群名称
node.name: "harold_coordinator_1"           #节点名称

# 2. You want this node to only serve as a master: to not store any data and
#    to have free resources. This will be the "coordinator" of your cluster.
#
node.master: true
node.data: false

discovery.zen.ping.unicast.hosts: ["vm11", "vm12", "vm13", "vm14", "vm15", "vm16"] #自动发现节点hosts

workhorse(Data数据节点):

cluster.name: harold                    #集群名称
node.name: "harold_data_1"              #节点名称

# 1. You want this node to never become a master node, only to hold data.
#    This will be the "workhorse" of your cluster.
#
node.master: false
node.data: true

discovery.zen.ping.unicast.hosts: ["vm11", "vm12", "vm13", "vm14", "vm15", "vm16"] #自动发现节点hosts

配置完,启动后,/_plugin/head/页面应该是这个样子:
ElasticSearch 集群

这样配置完的集群应该就是类似这样的:

ElasticSearch 架构图

可以使用curl初始化Index的主分片复制分片:

curl -XPUT -d'{"settings":{"number_of_shards":6, "number_of_replicas":1}}' http://vm11:9200/app1

Tip:

number_of_shards 主分片在集群中的总数量
number_of_replicas 每个主分片的复制分片数量

#复制分片在今后的分布式集群变化过程中,随时都可以根据业务进行新增或减少:
curl -XPUT -d'{"number_of_replicas":2}' http://vm11:9200/app1/_settings
#另外,ElasticSearch在没有任何索引的情况下新增一个文档,便自动创建了索引,为避免发生这种情况,可以在配置文件中添加:
action.auto_create_index: false

删除Index:

curl -XDELETE http://vm11:9200/app1

在当前版本中,这样组建集群会有一个小问题:

当单独把Master CoordinatorDown掉后,/_plugin/head/插件页面会是这个样子:
ElasticSearch
但可喜的是,并不影响集群与集群客户端之间数据的CRUD操作。
数据有所改变而且较长一段时间后(大约10几分钟?),/_plugin/head/插件页面会恢复正常。

贴下PHP操作ElasticSearch的多进程并发测试代码吧,做下记录:

<?php
class es extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'es:test';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description.';

    private $hosts = ["vm11:9200"];
    private $index = "app1";
    private $type = "users1";
    private $process = 200;
    private $sum = 10000;
    private $num_per_proc;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
        $this->sum % $this->process !== 0 && die("invalid num. \n");
        $this->num_per_proc = $this->sum / $this->process;
    }

    private function insert()
    {
        $es = new ClientBuilder();
        $es->setHosts($this->hosts);
        $client = $es->build();

        $words = str_split("abcdefghijklmnopqrstuvwxyz");

        $birth_year = [];
        for ($i = 1; $i <= 50; $i++) {
            $birth_year[] = 1960 + $i;
        }

        $type = ['1', '2', '3', '4'];

        $process = [];
        for ($p = 0; $p < $this->process; $p++) {
            $process[] = new \swoole_process(function () use ($client, $birth_year, $type, $words, $p) {
                for ($i = $this->num_per_proc * $p; $i < $this->num_per_proc * ($p + 1); $i++) {
                    $client->index([
                        'index' => $this->index,
                        'type' => $this->type,
                        'id' => $i,
                        'body' => [
                            'birth_year' => $birth_year[array_rand($birth_year)],
                            'type' => $type[array_rand($type)],
                            'name' => $words[mt_rand(0, 25)] . $words[mt_rand(0, 25)] . $words[mt_rand(0, 25)] . $words[mt_rand(0, 25)],
                            'height' => mt_rand(150, 200),
                            'weight' => mt_rand(40, 200),
                            'test' => 1,
                            'userid' => $i
                        ]
                    ]);
                }
            });
        }

        foreach ($process as $p) {
            $pid = $p->start();
            echo $pid . "\n";
        }
    }

    private function update()
    {
        $es = new ClientBuilder();
        $es->setHosts($this->hosts);
        $client = $es->build();

        $process = [];
        for ($i = 0; $i < $this->process; $i++) {
            $process[] = new \swoole_process(function () use ($client, $i) {
                $response = $client->search([
                    'index' => $this->index,
                    'type' => $this->type,
                    'size' => $this->num_per_proc,
                    'from' => $this->num_per_proc * $i,
                    'sort' => "userid:asc"
                ]);
                foreach ($response['hits']['hits'] as $v) {
                    $id = $v['_id'];
                    $test = $v['_source']['test'];
                    $test++;
                    file_put_contents("/tmp/s", $test . "\n", FILE_APPEND);

                    $client->update([
                        'index' => $this->index,
                        'type' => $this->type,
                        'id' => $id,
                        'body' => [
                            'doc' => [
                                'test' => $test
                            ]
                        ]
                    ]);
                }
            });
        }

        foreach ($process as $p) {
            $pid = $p->start();
            echo $pid . "\n";
        }
    }

    private function gets()
    {
        $es = new ClientBuilder();
        $es->setHosts($this->hosts);
        $client = $es->build();

        $response = $client->search([
            'index' => $this->index,
            'type' => $this->type,
            'size' => 5000,
            'from' => 500,
            'sort' => "userid:asc"
        ]);
        foreach ($response['hits']['hits'] as $v) {
            $id = $v['_id'];
            $test = $v['_source']['test'];
            // file_put_contents("/tmp/s", $test . "\n", FILE_APPEND);
            var_dump($test);
        }
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $this->insert();
    }
}

转载于:https://www.cnblogs.com/Harold-Hoo/p/4951235.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Elasticsearch集群搭建是指在多台服务器上安装和配置Elasticsearch,使它们能够协同工作以提供更高的可用性和性能。搭建Elasticsearch集群需要考虑多个方面,包括节点配置、数据分片、负载均衡等。具体步骤包括安装Java、安装Elasticsearch、配置节点、配置数据分片、配置负载均衡等。在搭建过程中需要注意一些细节,如节点之间的通信、数据备份和恢复等。 ### 回答2: Elasticsearch是一个开源的分布式搜索和分析引擎。它是基于Lucene库的,并且提供了一个RESTful API对外提供服务,可以在大数据量环境下,快速,准确地检索和分析数据。 Elasticsearch可以集群化部署,以实现数据的高可用和水平扩展。一个Elasticsearch集群通常由多个节点组成,节点可以运行在不同的物理机器或虚拟机器上。节点之间互相通信,协作完成数据的索引和查询。 以下是关于如何搭建Elasticsearch集群的简单介绍: 1. 安装Java环境 Elasticsearch基于Java开发,所以需要安装Java环境。建议使用OpenJDK 8或者Oracle JDK 8。 2. 下载并解压缩ElasticsearchElasticsearch官网下载最新版本的软件包,解压缩到您计划使用的目录,例如"/usr/share/elasticsearch"。 3. 配置Elasticsearch节点 在每个节点上设置Elasticsearch节点配置。其中一个最重要的配置是“cluster.name”,每个节点必须将其设置为相同的名称来加入同一个集群。 4. 配置群集发现 群集发现的主要功能是检测新加入或退出群集中的节点。Elasticsearch使用多种发现方法,如多播、单播、EC2自动发现等等。一般地,多播方式不太可靠,建议使用单播等有保障的方式。 5. 启动Elasticsearch节点 在每个节点上启动Elasticsearch进程。通过访问"http://localhost:9200"可以检查Elasticsearch是否已经成功启动。 6. 配置索引和shard副本 Elasticsearch通过将数据分割成多个索引、分片以及副本来实现水平扩展和高可用性。索引和shard参数的设计需要根据实际需求来确定。 7. 安全配置 在集群环境下,安全配置是非常必要的。主要的安全措施包括传输层安全性、节点访问控制、访问审计等等。最好参考官方文档来设置安全措施。 上述步骤仅是一个简单的概述,Elasticsearch集群搭建还需要考虑到具体的应用需求、硬件资源、数据量和查询性能等方面。建议在实际操作中进行详细研究和调整。 ### 回答3: Elasticsearch是当今最流行的搜索引擎之一,它具有高效、稳定和可扩展等优点,并且广泛应用于各种企业应用程序中。部署Elasticsearch集群不仅可以提高搜索速度和搜索质量,而且仍然可以提供可靠性和冗余性,以保障整个集群的高可用性。本文将讨论如何搭建Elasticsearch集群。 搭建Elasticsearch集群的前置条件是已经拥有多台服务器,具备以下要求: 1. 操作系统:Linux、Windows等 2. JDK版本:1.8及以上 3. Elasticsearch版本:7.x 4. 硬件要求:主机内存可以根据实际情况进行调整,但是最好不要低于4GB。 5. 硬盘要求:建议每台服务器都有一块专门用于存储数据的硬盘,以便于管理和备份。 6. 网络要求:每台服务器都需要分别配置一个IP地址,以便于节点相互通信和集群的建立。 下面具体讲解如何搭建Elasticsearch集群: 第一步:安装JDK环境 Elasticsearch是基于Java语言开发的,因此需要安装JDK环境。安装完成后,通过运行java -version 命令来检查JDK环境是否安装成功。 第二步:安装Elasticsearch 可以从Elasticsearch官网下载最新版本的安装包压缩包。下载完成后,使用解压命令将其解压到任意目录下。 第三步:配置Elasticsearch 每台服务器的配置都包括以下关键参数: cluster.name:集群的名称,因为每个节点都只能加入到同一个集群之中,所以集群名称必须一致。 node.name:节点的名称,每个节点都需要有唯一的名称标识,以便于集群管理和监控。 network.host:设置节点的IP地址,在多台服务器中,每个节点都需要拥有一个唯一的IP地址。 第四步:设置集群节点 节点具有容错性和冗余性,在Elasticsearch集群中至少需要2个节点。建议将节点分配在不同的服务器上,以便于在故障时可以再次启动其他节点来覆盖故障节点。 节点之间相互交换有关集群的信息,通过访问任何一个节点,都可以获得有关整个集群的信息。 第五步:优化集群性能 为了提高整个集群的性能,我们需要设置Elasticsearch的Java虚拟机(JVM)参数,这将有助于提高集群吞吐量、降低请求延迟、减少垃圾收集时间等。 例如,可以调整Xms和Xmx这两个参数来控制Java虚拟机使用的内存,以达到优化集群性能的目的。 总结 在本文中,我们简单介绍了如何在多台服务器上搭建Elasticsearch集群。具体而言,我们需要完成安装JDK、安装Elasticsearch、配置Elasticsearch、设置集群节点和优化集群性能等步骤。如果您在集群搭建过程中遇到了问题,可以参考Elasticsearch的官方文档或者社区贡献者的博客。通过合理设置,可以为整个集群提供高效、稳定、可扩展的搜索服务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值