目录
1:ES数据同步
1.1:为什么进行数据同步
因为ES中的是数据来自业务数据也就是数据库,比如mysql等,那么就需要把数据库的数据同步到ES中,那么什么时候进行数据同步呢?
1:直接同步:我们可以在进行mysql的crud的时候,直接把数据插入ES,缺点是增加操作时间,并且跟业务耦合,增加耗时
2:间接同步:我们可以在进行mysql的crud的时候,把数据发送到消息中间件,比如MQ,减少业务耦合,增加相应时间,削峰填谷
1.2:数据同步到RocketMQ
1:pom.xml导入jar,这里是springboot3.X、ES8.X、RocketMQ5.X 版本
<!--springboot帮我们自动集成了es,所以只需要引入下面这一个依赖即可-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>com.google.uzaygezen</groupId>
<artifactId>uzaygezen-core</artifactId>
<version>0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.uzaygezen</groupId>
<artifactId>uzaygezen-core</artifactId>
<version>0.2</version>
<scope>compile</scope>
</dependency>
<!--springboot3.X rocketmq-spring整合-->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>2.2.3</version>
</dependency>
2:解决RockeMQ5.X和SpringBoot3.X的兼容想问题
地址:Spring boot 3.0整合RocketMQ及不兼容的问题_rocketmq springboot3-CSDN博客
3:配置RocketMQConfig
@Configuration
public class RocketMQConfig {
@Value("${rocketmq.producer.group}")
private String producerGroup;
@Value("${rocketmq.name-server}")
private String nameServer;
/**
* 由于使用的Spring版本是3.0.0以上,与rocketMq不是很兼容,对于rocketMqTemplate
* 的自动注入存在差异,如果不采用这种方式注入则会报出缺少bean的信息
*/
@Bean
public RocketMQTemplate rocketMQTemplate(){
System.out.println("producerGroup:"+producerGroup);
System.out.println("nameServer:"+nameServer);
RocketMQTemplate rocketMQTemplate = new RocketMQTemplate();
//设置默认的DefaultMQProducer
DefaultMQProducer defaultMqProducer = new DefaultMQProducer();
defaultMqProducer.setProducerGroup(producerGroup);
defaultMqProducer.setNamesrvAddr(nameServer);
rocketMQTemplate.setProducer(defaultMqProducer);
return rocketMQTemplate;
}
}
4:配置springboot的yml
#rocketmq的配置
rocketmq:
name-server: localhost:9876
producer:
group: producer_group1
consumer:
topic: topic26
5:消息生产者发送消息
@Autowired
RocketMQTemplate rocketMQTemplate;
@Value("${rocketmq.consumer.topic}")
private String topic;
@Value(value = "${rocketmq.consumer.topic1}:${rocketmq.consumer.topic2}")
private String syncTag;
//发现消息到RocketMQ
@Override
public void sendMQ(TbHotel tbHotel) throws JsonProcessingException {
//发送json
ObjectMapper objectMapper=new JsonMapper();
String json = objectMapper.writeValueAsString(tbHotel);
System.out.println("发送数据:"+json);
rocketMQTemplate.convertAndSend(topic,json);
}
6:消息接受者接收消息
@Service
@RocketMQMessageListener(
topic = "topic26",
consumerGroup = "consumerGroup26"
)
public class RocketMQConsumer1 implements RocketMQListener<String> {
@Autowired
ElasticsearchClient elasticsearchClient;
@Override
public void onMessage(String message) {
System.out.println("9002接受的消息是:"+message);
//将json转换为对象
ObjectMapper objectMapper=new ObjectMapper();
try {
TbHotel hotel = objectMapper.readValue(message, TbHotel.class);
System.out.println("实体转换:"+hotel);
//数据库查询到一条数据
TbHotelDoc hotelDoc=new TbHotelDoc(hotel);
System.out.println(hotelDoc);
//数据插入ES 无论修改数据还是增加数据都是 插入
IndexRequest indexRequest=new IndexRequest.Builder<TbHotelDoc>()
.id(hotel.getId().toString())
.index("hotel")
.document(hotelDoc).build();
elasticsearchClient.index(indexRequest);
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2:ES集群
2.1:三台服务器搭建集群
在ES中存在单机处理上限,以及单机的稳定性,所以集群的搭建是必不可少的
假如我们搭建三台服务器作为集群9200,9201,9202
2.2:ES的集群节点角色
在我们搭建的三个节点构成的集群中,每个节点都是相同的类型,都具有如图的特点
1:都是候选主节点
2:都具有数据节点的功能:数据局存储、搜索、聚合、crud
3:都是ingest,具有数据存储预处理功能
这有什么缺点呢?
假如新增id=1、2、3的数据 。数据都会连接到主节点,主节点根据hash取模,然后将数据插入节点1、2、3中(查询同理)。这里就可以看出来,主节点具备记录集群状态,决定分片在那个节点的主节点功能,还得具有数据的存储、搜索功能,也就是上边的三种类型,都具备。当数据量很大的时候,crud的时候,主节点压力很大哦。这就是不划分职责的情况。
在大公司中,集群可能有几百个节点,那么所有的crud都要经过主节点hsah,主节点太累,所以需要把节点按照权限划分,架构出来新的架构
大型ES集群的架构如下
ES集群新增数据如下图:
ES集群查询数据如下图:
2.3:ES集群服务的搭建
1:这里没有自己搭建,参考网上搭建案例
2:不使用kinaba来连接集群,而是cerebo软件来连接集群
3: cerebo控制台查看集群
4:创建索引的DSL,添加数据,根据id取模路由到分片,分片不能再改了
5:查询数据
2.4:ES集群故障转移
我们手动关闭主节点es01服务:
然后开始重新选举,进行故障转移