elastcisearch——下

ES集群:

在上我们讲解了es的单节点模式,今天我们说一说ES的集群。

ES的集群结果和角色:

首先我们先知道什么叫元数据
元数据就是描述数据的信息。其中ES集群的元数据比如有,分片个数,分片的储存位置,document文档中的index,type,version,这些都可以叫做元数据。

角色1:master主节点
首先有主节点就应该联想到高可用,在一个ES集群中,会指定多个master,但是只有一个leader,其他的master同步他的元数据,leader宕机时就会有其他master来顶替。

角色2:data数据节点
数据节点就是用来存放master的5个分片和5个备用分片的。从下图也可以看出,随着master的增多,数据节点也会增多,每个数据节点保存的分片数量就越少。

角色3:负载均衡节点
同步元数据,给外界链接使用,也可以说是对外的一个统一接口。

角色4:协调器
协调器可以通过链接一个集群的所有节点,将集群链接成一整个服务。就是各个模块的相互调用。

在这里插入图片描述

脑裂:

当es集群中,出现了两个leader master就称为脑裂。
为何会有两个leader?
如果有网络波动产生,其他的master以为leader master宕机了,于是投票产生了新的leader,等网络恢复正常,就产生了两个leader。
如何避免脑裂?
在配置文件中,可以配置最小有效集群数(集群中所有master节点个数过半数)。
比如有3个master,因为网络波动,leader master和其他两个master失去了联系,这个时候从分区的角度我们看出,leader master是一个节点小于最小有效集群数,所以他的leader失效;而另外一个分区是两个节点,满足最小有效集群数,所以可以新选出leader。

ES的java客户端——TransportClient

1.导入依赖:

<dependency>
         <groupId>org.elasticsearch.client</groupId>
         <artifactId>transport</artifactId>
         <version>5.5.2</version>
</dependency>
<dependency>
         <groupId>org.elasticsearch</groupId>
         <artifactId>elasticsearch</artifactId>
         <version>5.5.2</version>
</dependency>

2.客户端——索引管理
Transportclient对象,底层需要java的socket支持,创建连接时需要通过socket代码获取ip地址和端口。

public class ESTest {
	
    //通过私有属性 通过@Before构建一个连接对象
    private TransportClient client;
    
    //给私有属性赋值 提供ip port
    //Before的作用就是测试@Test 每次执行之前都会执行
    //Before
    @Before
    public void init() throws UnknownHostException {

        //给我的client赋值 10.9.151.60:9300

        //传递一个settings值 定义连接的集群名称 elasticsearch

       Settings setting= Settings.builder()

                .put("cluster.name","elasticsearch").build();
       
       client=new PreBuiltTransportClient(Settings);

       //收集ip和端口的对象address

        InetSocketTransportAddress address= new InetSocketTransportAddress(InetAddress.getByName("10.9.151.60"),9300);

        //添加到client对象

        client.addTransportAddress(address);

    }

}

接上个类里:

   //集群的索引管理

    //创建索引,删除索引,获取查看个索引

    //transportclient封装了2中通的操作逻辑

    //对索引对集群的操作 需要先获取admin管理对象

    @Test

    public void indexManage() throws IOException {

        //创建索引 http://10.9.151.60:9200/index01 put

        //获取admin 可以管理集群cluster也可以管理indices

        AdminClient admin = client.admin();

        //操作index

        IndicesAdminClient indices = admin.indices();

        ClusterAdminClient cluster = admin.cluster();

        //建一个索引 index07

        //indices.create();//方法调用,命令就发送

        //CreateIndexRequestBuilder createIndexRequest =

                //indices.prepareCreate("index07");//没有发送命令

        //prepare**方法调用没法送命令,但是获取了返回值request对象

        //想把代码命令发送出去

        //CreateIndexResponse createIndexResponse = createIndexRequest.get();

        //response解析就是创建索引的返回值 {"acknowlaged","shards_acknowlaged"}

        //createIndexResponse.isShardsAcked();

        //createIndexResponse.isAcknowledged();

        GetAliasesRequestBuilder GetAliasesRequest = indices.prepareGetAliases("index07");

        GetMappingsRequestBuilder getMappingsRequest = indices.prepareGetMappings("index02");

        IndicesExistsRequestBuilder indicesExistesRequest = indices.prepareExists("index07");

        GetMappingsResponse getMappingsResponse = getMappingsRequest.get();

        System.out.println("index07存在吗:"+indicesExistesRequest.get().isExists());

 

        /*ImmutableOpenMap<String, ImmutableOpenMap<String, MappingMetaData>> mappings = getMappingsResponse.getMappings();

        ImmutableOpenMap<String, MappingMetaData> index02 = mappings.get("index02");

        MappingMetaData article = index02.get("article");

        Map<String, Object> stringObjectMap = article.sourceAsMap();

        String content =(String)stringObjectMap.get("content");

        System.out.println(content);*/

 

        /*System.out.println("content:type值:"+);//text

        ObjectLookupContainer<String> keys = article.keys();

        System.out.println("article下的所有域属性:"+keys.toString());

*/

        //常用的方法,创建索引,不存在时创建索引

        //prepareCreate prepareExists prepareDelete;

    }

3.客户端——文档管理
还是接上个类里

  //文档管理 增删查改

    @Test

    public void docManage() throws JsonProcessingException {

        //新增文档,读取数据源封装文档数据写入es

        Product product=new Product();

        product.setProductCategory("手机");

        product.setProductId("好用");

        product.setProductId("123456");

        product.setProductImgurl("http://image.jt.com");

        product.setProductName("华为手机");

        product.setProductNum(50);

        product.setProductPrice(50.0);

        //http://10.9.151.60:9200/index/article/1 -d

        //将其转化为json

        ObjectMapper mapper=new ObjectMapper();

        String json = mapper.writeValueAsString(product);

        //通过client的prepare方法获取request request.get

        IndexRequestBuilder request = client.prepareIndex("index07", "product", product.getProductId());

        //request添加请求数据 json字符串

        request.setSource(json);

        IndexResponse indexResponse = request.get();

        //新建document返回字符串json _index _type _id _version

        long version = indexResponse.getVersion();

        System.out.println("创建version:"+version);

        //删除document

        client.prepareDelete("index07","product","123456");

        //获取

        client.prepareGet("index07","product","123456");

    }

4.客户端——搜索

//搜索

    @Test

    public void search(){

        //通过query对象的封装 实现不同搜索逻辑

        //搜索的过程的分页时浅查询

        TermQueryBuilder query = QueryBuilders.termQuery("title", "介");

        //搜索

        SearchRequestBuilder request = client.prepareSearch("index02");

        //搜索条件

        request.setQuery(query);

        //搜索分页数据,其实位置,条数

        request.setFrom(0);//limit start

        request.setSize(5);

 

        SearchResponse searchResponse = request.get();

        //从searchResponse解析查询结果

        SearchHits topDocs = searchResponse.getHits();

        System.out.println("查询总数:"+topDocs.totalHits);

        //遍历数组

        SearchHit[] scoreDocs = topDocs.getHits();

        for (SearchHit hit:scoreDocs){

            //获取一个doument返回结果

            //{"id":"","title"}

            System.out.println("source的json:"+hit.getSourceAsString());

        }

        //easymall将productJson转化为product对象去使用.

    }

springBoot中使用es客户端:

这里的思路是,把初始化创建TransportClient对象的过程,做成一个配置类,把初始化方法添加上@bean,这样spring初始化的时候,这个方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义。

@Configuration
//配合@Configuration实现配置类中属性初始化赋值
//@Value作用一样可以读取properties
//自定义前缀,多级赋值
@ConfigurationProperties("easymall.es")
public class ESConfig {
   /* private String name;//只要properties中
    //有一个属性easymall.es.name
    //在properties文件中
    //easymall.es.nodes=10.9.9.9:9300,10.9.9.9:9500
    private List<String> nodes;//["10.9.9.9:9300","10.9.9.9:9500"]
    private String nodes;//nodes=10.9.9.9:9300,10.9.9.9:9500
*/
    /*public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }*/
    //配置类的作用就是生成一个容器管理的对象Transport
    //创建对象时,需要ip:port的es节点集群
    //easymall.es.nodes=es01,es02,es03
    private List<String> nodes;
    public List<String> getNodes() {
        return nodes;
    }
    public void setNodes(List<String> nodes) {
        this.nodes = nodes;
    }
    @Bean
    public TransportClient initClient(){
        System.out.println("开始创建一个es连接客户端");
        System.out.println("nodes的个数"+nodes.size());
        //new个对象
        TransportClient client=new
        PreBuiltTransportClient(Settings.EMPTY);
        //利用nodes获取连接对象ip:port
        for(String node:nodes){
            //node=""10.9.48.69""9300";
            String host=node.split(":")[0];
            int port=Integer.parseInt(node.
                    split(":")[1]);
            //做一个address
            InetSocketTransportAddress address;
            try{
               address=
                new InetSocketTransportAddress(
                InetAddress.getByName(host),port);
            }catch (Exception e){
                e.printStackTrace();
                continue;
            }
            client.addTransportAddress(address);
        }
        return client;
       // return new PreBuiltTransportClient(Settings.EMPTY);
    }
}

在application文件中,需要说明ES集群的IP地址和端口号,这样方法中的nodes就知道值是多少了:

easymall.es.nodes=10.9.48.69:9300,10.9.151.60:9300

之后在需要使用transportclient对象的地方,直接使用@Autowired注入,就可以使用transportclient对象的索引操作方法,文档操作方法,搜索方法了。

猜你喜欢

转载自blog.csdn.net/weixin_42596778/article/details/106649501