Redis:主从复制

目录

    • 概念
    • 配置步骤
    • 通过命令配置
    • 主从复制原理
    • 薪火相传
    • 反客为主
    • 哨兵(Sentinel)模式
      • 原理
      • 配置
      • SpringBoot整合Sentinel模式

概念

主机更新后根据配置和策略,自动同步到备机的master/slave机制,Master以写为主,Slave以读为主。

作用:

  • 读写分离,性能扩展,降低主服务器的压力
  • 容灾,快速恢复,主机挂掉时,从机变为主机

在这里插入图片描述

配置步骤

以配置1主2从为例。现实中是需要3台机器的,为了方便,我们就在一台机器上来演示,通过不同的端口来区分机器,3台机器的配置。

角色端口
master(主)6379
slave1(从)6380
slave2(从)6381

在这里插入图片描述

配置主从步骤如下

1)创建案例工作目录:master-slave

执行下面命令创建 /opt/master-slave 目录,本次所有操作,均在 master-slave 目录进行

ps -ef | grep redis | awk -F" " '{print $2;}' | xargs kill -9 # 方便演示,停止所有的 redis
mkdir /opt/master-slave
cd /opt/master-slave/

2)将redis.conf复制到master-slave目录

cp /opt/redis-6.2.1/redis.conf /opt/master-slave/

3)创建master的配置文件:redis-6379.conf

在/opt/master-slave目录创建 redis-6379.conf 文件,内容如下,注意 192.168.200.129 是这个测试机器的ip,大家需要替换为自己的

#redis.conf是redis原配置文件,内部包含了很多默认的配置,这里使用include将其引用,相当于把 redis.conf内容直接贴进来了 
include /opt/master-slave/redis.conf 
daemonize yes 
bind 192.168.200.129 
#配置密码 
requirepass 123456 
dir /opt/master-slave/ 
logfile /opt/master-slave/6379.log 

#端口 
port 6379 
#rdb文件 
dbfilename dump_6379.rdb
#pid文件 
pidfile /var/run/redis_6379.pid

4)创建slave1的配置文件:redis-6380.conf

在/opt/master-slave目录创建 redis-6380.conf 文件,内容如下,和上面master的类似,多了后面2行

include /opt/master-slave/redis.conf 
daemonize yes 
bind 192.168.200.129 
requirepass 123456 
dir /opt/master-slave/ 
port 6380 
dbfilename dump_6380.rdb 
pidfile /var/run/redis_6380.pid 
logfile /opt/master-slave/6380.log 

#用来指定主机:slaveof 主机ip 端口 
slaveof 192.168.200.129 6379 
#主机的密码
masterauth 123456

5)创建slave2的配置文件:redis-6381.conf

include /opt/master-slave/redis.conf 
daemonize yes 
bind 192.168.200.129 
requirepass 123456 
dir /opt/master-slave/ 
port 6381 
dbfilename dump_6381.rdb
pidfile /var/run/redis_6381.pid 
logfile /opt/master-slave/6381.log

#用来指定主机:slaveof 主机ip 端口 
slaveof 192.168.200.129 6379 
#主机的密码
masterauth 123456

6)启动master和slave

# 启动master
redis-server /opt/master-slave/redis-6379.conf
# 启动slave1
redis-server /opt/master-slave/redis-6380.conf
# 启动slave2
redis-server /opt/master-slave/redis-6381.conf

7)查看主机的信息

通过redis-cli命令连接主机,如下

redis-cli -h 192.168.200.129 -p 6379 -a 123456

通过下面命令,查看主机信息

info Replication

在这里插入图片描述

8)查看slave1的信息

通过下面2个命令查询从机slave1的信息

redis-cli -h 192.168.200.129 -p 6380 -a 123456 
info Replication

如下

在这里插入图片描述

9)验证主从同步效果

在master上面执行下面2个命令

192.168.200.129:6379> flushdb 
OK
192.168.200.129:6379> set name ready 
OK
192.168.200.129:6379> set age 30 
OK

到slave1或slave2上执行下面命令,可以看出来数据已经同步过来了

192.168.200.129:6380> mget name age 
1) "ready" 
2) "30" 

通过命令配置

1)执行下面命令,连接slave1

redis-cli -h 192.168.200.129 -p 6380 -a 123456

2)执行下面命令,设置master的密码

由于master需要密码,所以在slave1中需要指定master的密码,否则无法同步数据。

config set masterauth 123456

3)执行下面命令,指定slave1的作为master的从机

slaveof 192.168.200.129 6379

主从复制原理

  • slave启动成功连接到master后,会给master发送数据同步消息(发送sync命令)
  • master接收到slave发来的数据同步消息后,把主服务器的数据进行持久化到rdb文件,同时会收集接收到的用于修改数据的命令,master将传rdb文件发送给你slave,完成一次完全同步
  • 全量复制:而slave服务在接收到master发来的rdb文件后,将其存盘并加载到内存
  • 增量复制:master继续将收集到的修改命令依次传给slave,完成同步
  • 但是只要重新连接master,一次完全同步(全量复制)将会被自动执行

薪火相传

若master下面挂很多slave,master会有压力,实际上slave下面也可以挂slave,如下图,配置这里就不演示了,和上面的类似。

在这里插入图片描述

反客为主

当master挂掉之后,我们可以从slave中选择一个作为主机。

比如我们想让slave1作为主机,那么可以在slave1上执行下面的命令就可以了。

slaveof no one

此时slave1就变成主机了,然后再去其他slave上面执行 slaveof 命令将其挂在slave1上。

这种主备切换有个缺点:需要手动去执行命令去操作,不是太方便。

下面来介绍另外一种方式:哨兵模式,主挂掉之后,自动从slave中选举一个作为主机,自动实现故障转移。

哨兵(Sentinel)模式

哨兵(Sentinel)模式即为反客为主的自动版,能够自动监控master是否发生故障,如果故障了会根据投票数从slave中挑选一个作为master,其他的slave会自动转向同步新的master,实现故障自动转义。

原理

sentinel会按照指定的频率给master发送ping请求,看看master是否还活着,若master在指定时间内未正常响应sentinel发送的ping请求,sentinel则认为master挂掉了,但是这种情况存在误判的可能,比如:可能master并没有挂,只是sentinel和master之间的网络不通导致,导致ping失败。

为了避免误判,通常会启动多个sentinel,一般是奇数个,比如3个,那么可以指定当有多个sentinel都觉得master挂掉了,此时才断定master真的挂掉了,通常这个值设置为sentinel的一半,比如sentinel的数量是3个,那么这个量就可以设置为2个。

当多个sentinel经过判定,断定master确实挂掉了,接下来sentinel会进行故障转移:会从slave中投票选出一个服务器,将其升级为新的主服务器, 并让失效主服务器的其他从服务器slaveof指向新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。

配置

1)需求

下面我们来实现1主2从3个sentinel的配置,当从的挂掉之后,要求最少有2个sentinel认为主的挂掉了,才进行故障转移。

为了方便,我们在一台机器上进行模拟,我的机器ip是:192.168.200.129,通过端口来区分6个不同的节点(1个master、2个slave、3个sentinel),节点配置信息如下:

在这里插入图片描述

2)创建案例工作目录:sentinel

执行下面命令创建 /opt/sentinel 目录,本次所有操作,均在 sentinel 目录进行:

# 方便演示,停止所有的redis 
ps -ef | grep redis | awk -F" " '{print $2;}' | xargs kill -9 
mkdir /opt/sentinel 
cd /opt/sentinel/

3)将redis.conf复制到sentinel目录

redis.conf 是redis默认配置文件

cp /opt/redis-6.2.1/redis.conf /opt/sentinel/

4)创建master的配置文件:redis-6379.conf

在/opt/sentinel目录创建 redis-6379.conf 文件,内容如下,注意 192.168.200.129 是这个测试机器的ip,大家需要替换为自己的

include /opt/sentinel/redis.conf 
daemonize yes 
bind 192.168.200.129 
dir /opt/sentinel/

port 6379 
dbfilename dump_6379.rdb 
pidfile /var/run/redis_6379.pid 
logfile "./6379.log

5)创建slave1的配置文件:redis-6380.conf

在/opt/sentinel目录创建 redis-6380.conf 文件,内容如下,和上面master的类似,只是将6379换成6380了

include /opt/sentinel/redis.conf 
daemonize yes 
bind 192.168.200.129 
dir /opt/sentinel/

port 6380
dbfilename dump_6380.rdb 
pidfile /var/run/redis_6380.pid 
logfile "./6380.log

6)创建slave2的配置文件:redis-6381.conf

在/opt/sentinel目录创建 redis-6381.conf 文件,内容如下

include /opt/sentinel/redis.conf 
daemonize yes 
bind 192.168.200.129 
dir /opt/sentinel/

port 6381
dbfilename dump_6381.rdb 
pidfile /var/run/redis_6381.pid 
logfile "./6381.log

7)启动master、slave1、slave2

redis-server /opt/sentinel/redis-6379.conf 
redis-server /opt/sentinel/redis-6380.conf 
redis-server /opt/sentinel/redis-6381.conf

8)配置slave1和slave2为master的从库

执行下面命令,连接slave1

redis-cli -h 192.168.200.129 -p 6380

执行下面命令,指定slave1的作为master的从机

slaveof 192.168.200.129 6379

Slave2同理。

9)创建sentinel1的配置文件:sentinel-26379.conf

在/opt/sentinel目录创建 sentinel-26379.conf 文件,内容如下

# 配置文件目录 
dir /opt/sentinel/
# 日志文件位置 
logfile "./sentinel-26379.log"
# pid文件 
pidfile /var/run/sentinel_26379.pid 
# 是否后台运行 
daemonize yes 
# 端口 
port 26379
# 监控主服务器master的名字:mymaster,IP:192.168.200.129,port:6379,最后的数字2表示当 Sentinel集群中有2个Sentinel认为master存在故障不可用,则进行自动故障转移 
sentinel monitor mymaster 192.168.200.129 6379 2 
# master响应超时时间(毫秒),Sentinel会向master发送ping来确认master,如果在20秒内,ping 不通master,则主观认为master不可用 
sentinel down-after-milliseconds mymaster 60000 
# 故障转移超时时间(毫秒),如果3分钟内没有完成故障转移操作,则视为转移失败 
sentinel failover-timeout mymaster 180000 
# 故障转移之后,进行新的主从复制,配置项指定了最多有多少个slave对新的master进行同步,那可以理 解为1是串行复制,大于1是并行复制 
sentinel parallel-syncs mymaster 1 
# 指定mymaster主的密码(没有就不指定) 
# sentinel auth-pass mymaster 123456

10)创建sentinel2的配置文件:sentinel-26380.conf

在/opt/sentinel目录创建 sentinel-26380.conf 文件,内容如下

# 配置文件目录
dir /opt/sentinel/
# 日志文件位置
logfile "./sentinel-26380.log"
# pid文件
pidfile /var/run/sentinel_26380.pid
# 是否后台运行
daemonize yes
# 端口
port 26380
# 监控主服务器master的名字:mymaster,IP:192.168.200.129,port:6379,最后的数字2表示当Sentinel集群中有2个Sentinel认为master存在故障不可用,则进行自动故障转移
sentinel monitor mymaster 192.168.200.129 6379 2
# master响应超时时间(毫秒),Sentinel会向master发送ping来确认master,如果在20秒内,ping 不通master,则主观认为master不可用
sentinel down-after-milliseconds mymaster 60000
# 故障转移超时时间(毫秒),如果3分钟内没有完成故障转移操作,则视为转移失败 
sentinel failover-timeout mymaster 180000 
# 故障转移之后,进行新的主从复制,配置项指定了最多有多少个slave对新的master进行同步,那可以理 解为1是串行复制,大于1是并行复制
sentinel parallel-syncs mymaster 1 
# 指定mymaster主的密码(没有就不指定) 
# sentinel auth-pass mymaster 123456

11)创建sentinel3的配置文件:sentinel-26381.conf

在/opt/sentinel目录创建 sentinel-26381.conf 文件,内容如下

# 配置文件目录 
dir /opt/sentinel/ 
# 日志文件位置 
logfile "./sentinel-26381.log" 
# pid文件
pidfile /var/run/sentinel_26381.pid 
# 是否后台运行 
daemonize yes 
# 端口 
port 26381 
# 监控主服务器master的名字:mymaster,IP:192.168.200.129,port:6379,最后的数字2表示当 Sentinel集群中有2个Sentinel认为master存在故障不可用,则进行自动故障转移 
sentinel monitor mymaster 192.168.200.129 6379 2 
# master响应超时时间(毫秒),Sentinel会向master发送ping来确认master,如果在20秒内,ping 不通master,则主观认为master不可用 
sentinel down-after-milliseconds mymaster 60000 
# 故障转移超时时间(毫秒),如果3分钟内没有完成故障转移操作,则视为转移失败 
sentinel failover-timeout mymaster 180000 
# 故障转移之后,进行新的主从复制,配置项指定了最多有多少个slave对新的master进行同步,那可以理 解为1是串行复制,大于1是并行复制
sentinel parallel-syncs mymaster 1 
# 指定mymaster主的密码(没有就不指定)
# sentinel auth-pass mymaster 123456

12)启动3个sentinel

启动sentinel有2种方式

方式1:redis-server sentinel.conf --sentinel
方式2:redis-sentinel sentinel.conf

下面我们使用方式2来启动3个sentinel

/opt/redis-6.2.1/src/redis-sentinel /opt/sentinel/sentinel-26379.conf 
/opt/redis-6.2.1/src/redis-sentinel /opt/sentinel/sentinel-26380.conf 
/opt/redis-6.2.1/src/redis-sentinel /opt/sentinel/sentinel-26381.conf

13)分别查看3个sentinel的信息

分别对3个sentinel执行下面命令,查看每个sentinel的信息

redis-cli -p sentinel的端口 
info sentinel

sentinel1 的信息如下,其他2个sentinel的信息这里就不列了,大家自己去看一下

在这里插入图片描述

14)验证故障自动转移是否成功

step1:在master中执行下面命令,停止master

192.168.200.129:6379> shutdown

step2:等待2分钟,等待完成故障转移

sentinel中我们配置 down-after-milliseconds 的值是60秒,表示判断主机下线时间是60秒,所以我们等2分钟,让系统先自动完成故障转移。

step3:查看slave1的主从信息,如下

在这里插入图片描述

step4:查看slave2的主从信息,如下

在这里插入图片描述

slave2变成master了,且slave2变成slave1的从库了,完成了故障转移

step5:下面验证下slave1和slave2是否同步

在slave2中执行下面命令

192.168.200.129:6381> set address china 
OK

在slave1中执行下面命令,查询一下address的值,效果如下,说明slave2和slave1同步正常

192.168.200.129:6380> get address
"china"

15)恢复旧的master自动边slave

当旧的master恢复之后,会自动挂在新的master下面。

SpringBoot整合Sentinel模式

1)引入redis的maven配置

<dependency> 
<groupId>org.springframework.boot</groupId> 
<artifactId>spring-boot-starter-data-redis</artifactId> 
</dependency>

2)application.properties中配置redis sentinel信息

# redis sentinel主服务名称,这个可不是随便写的哦,来源于:sentinel配置文件中sentinel monitor后面跟的那个名称
spring.redis.sentinel.master=mymaster 
# sentinel节点列表(host:port),多个之间用逗号隔开 
spring.redis.sentinel.nodes=192.168.200.129:26379,192.168.200.129:26380,192.168. 200.129:26381 
# sentinel密码 
#spring.redis.sentinel.password=
# 连接超时时间(毫秒) 
spring.redis.timeout=60000 
# Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0 
spring.redis.database=0

3)使用RedisTemplate工具类操作redis

springboot中使用RedisTemplate来操作redis,需要在我们的bean中注入这个对象,代码如下:

@Autowired private RedisTemplate<String, String> redisTemplate; 

// 用下面5个对象来操作对应的类型
this.redisTemplate.opsForValue(); //提供了操作string类型的所有方法 
this.redisTemplate.opsForList(); // 提供了操作list类型的所有方法 
this.redisTemplate.opsForSet(); //提供了操作set的所有方法 
this.redisTemplate.opsForHash(); //提供了操作hash表的所有方法 \
this.redisTemplate.opsForZSet(); //提供了操作zset的所有方法

RedisTemplate示例代码

import org.redisson.client.RedisConnection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Ethan
 * @date 2023/11/30
 * @description
 */
@RestController
@RequestMapping("/redis")
public class RedisController {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * string测试
     * @return
     */
    @RequestMapping("/stringTest")
    public String stringTest() {
        this.redisTemplate.delete("name");
        this.redisTemplate.opsForValue().set("name", "路人");
        String name = this.redisTemplate.opsForValue().get("name");
        return name; }

    /***
     * list测试 *
     * * @return
     * */
    @RequestMapping("/listTest")
    public List<String> listTest() {
        this.redisTemplate.delete("names");
        this.redisTemplate.opsForList().rightPushAll("names", "刘德华", "张学友", "郭富城", "黎明");
        List<String> courses = this.redisTemplate.opsForList().range("names", 0, -1);
        return courses;
    }

    /**
     * set测试
     *
     * @return
     */
    @RequestMapping("setTest")
    public Set<String> setTest() {
        this.redisTemplate.delete("courses");
        this.redisTemplate.opsForSet().add("courses", "java", "spring", "springboot");
        Set<String> courses = this.redisTemplate.opsForSet().members("courses");
        return courses;
    }

    /**
     * hash测试
     *
     * @return
     */
    @RequestMapping("hashTest")
    public Map<Object, Object> hashTest() {
        this.redisTemplate.delete("userMap");
        Map<String, String> map = new HashMap<>();
        map.put("name", "路人"); map.put("age", "30");
        this.redisTemplate.opsForHash().putAll("userMap", map);
        Map<Object, Object> userMap = this.redisTemplate.opsForHash().entries("userMap");
        return userMap;
    }


    /**
     * 查看redis机器信息
     *
     * @return
     */
    @RequestMapping(value = "/info", produces = MediaType.TEXT_PLAIN_VALUE)
    public String info() {
        Object obj = this.redisTemplate.execute(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.execute("info");
            }
        }); return obj.toString();
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/207684.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python+Requests模块添加cookie

请求中添加cookies 对于某些网站&#xff0c;登录然后从浏览器中获取cookies&#xff0c;以后就可以直接拿着cookie登录了&#xff0c;无需输入用户 名密码。 一、在参数中添加cookie 在发送请求时使用cookies 代码示例&#xff1a; import requests # 1&#xff0c;在参数…

ZFPlayer 在tableView列表中播放视频架构设计

需求背景 需要在如图所示的列表中播放视频&#xff0c;并且播放视频在对应的卡片上&#xff0c;滚动结束的时候&#xff0c; 完整露出封面图的第一个视频自动播放 分析 根据需求&#xff0c;是滚动的时候获取符合条件的cell&#xff0c;并且 在cell的封面图上播放视频&#x…

CSS中的非布局样式+CSS布局 前端开发入门笔记(十一)

CSS中的非布局样式 在CSS中&#xff0c;非布局样式是指那些不会直接影响页面布局的样式。这些样式主要关注的是元素的颜色、字体、背景、边框、阴影等视觉效果。以下是一些常见的非布局CSS样式&#xff1a; 文本样式&#xff1a;包括字体&#xff08;font-family&#xff09;…

传统算法:使用 Pygame 实现归并排序

使用 Pygame 模块实现了归并排序的动画演示。首先,它生成一个包含随机整数的数组,并通过 Pygame 在屏幕上绘制这个数组的条形图。接着,通过归并排序算法对数组进行排序,动画效果可视化每一步的排序过程。在排序的过程中,程序将数组递归地分成两半,分别进行排序,然后再将…

小白备战蓝桥杯:Java常用API

一、什么是API 就是别人写好的一些类&#xff0c;给咱们程序员直接拿去调用即可解决问题的 我们之前接触过的Scanner和Random都是API 但java中提供的API很多&#xff0c;我们没有必要去学习所有的API&#xff0c;只需要知道一些常用的API&#xff0c;再借助帮助文档去使用AP…

从HumanEval到CoderEval: 你的代码生成模型真的work吗?

本文主要介绍了一个名为CoderEval的代码生成大模型评估基准&#xff0c;并对三个代码生成模型&#xff08;CodeGen、PanGu-Coder和ChatGPT&#xff09;在该基准上的表现进行了评估和比较。研究人员从真实的开源项目中的选取了代码生成任务来构建CoderEval&#xff0c;并根据对外…

Python函数专题(下)侯小啾python领航班系列(十三)】

Python函数专题(下)侯小啾python领航班系列(十三)】 大家好,我是博主侯小啾, 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹…

腾讯云年末感恩回馈:2核2G4M云服务器118元1年,新老用户同享!

腾讯云年末感恩回馈活动开始了&#xff0c;年度爆款2核2G4M云服务器118元/年&#xff0c;新老用户同享&#xff0c;记得抓住上云好时机&#xff01; 活动地址&#xff1a; 点此直达腾讯云年末感恩回馈 活动详情&#xff1a; 配置说明&#xff1a; 2核2G 独享CPU性能50GB SSD…

观《王牌对王牌:国宝回国》有感 —— AI绘画之古画修复对比图

一、前言 上周《王牌对王牌》节目的主题是《国宝回国》&#xff0c;而今天的AI绘画的灵感&#xff0c;就来源于这期节目。 下面这组图&#xff0c;左侧部分因时间的流逝而显现出褪色和损伤的痕迹&#xff0c;色彩变得暗淡&#xff0c;细节也因年代久远而变得模糊不清。 而右…

知虾平台丨优化Shopee店铺运营,提升销售利润——了解知虾平台

在如今竞争激烈的电商市场中&#xff0c;Shopee作为一家快速发展的平台&#xff0c;吸引了众多卖家加入。然而&#xff0c;要在Shopee上取得成功并实现可观的销售利润&#xff0c;并不是一件容易的事情。为了帮助卖家更好地了解市场趋势、优化商品关键词、监控竞争对手等&#…

c题目13:验证100以内的数是否满足哥德巴赫猜想。(任一大于2的偶数都可以写成两个质数之和)

每日小语 活下去的诀窍是&#xff1a;保持愚蠢&#xff0c;又不能知道自己有多蠢。——王小波 自己思考 即要让第一个质数与这个数减去第一个质数的值都为质数&#xff0c;所以要满足几个条件 1.abc 2.a为质数 3.b为质数 这里是否可以用到我之前刚学的自己设置的那个判断…

daima8资源网整站数据打包完整代码(集成了ripro9.1主题,开箱即用)

基于ripro9.1完全明文无加密后门版本定制开发&#xff0c;无需独立服务器&#xff0c;虚拟主机也可以完美运营&#xff0c;只要主机支持php和mysql即可。整合了微信登录和几款第三方的主题文件&#xff0c;看起来更美观一些。站长本人就是程序员&#xff0c;所以本站的代码资源…

力扣每日一题(2023-11-30)

力扣每日一题 题目&#xff1a;1657. 确定两个字符串是否接近 日期&#xff1a;2023-11-30 用时&#xff1a;21 m 07 s 时间&#xff1a;11ms 内存&#xff1a;43.70MB 代码&#xff1a; class Solution {public boolean closeStrings(String word1, String word2) {if(word1.…

全面预算管理平台让企业管理智慧升级

智能制造背景下&#xff0c;企业财务发展与业务、运营、服务等环节紧紧相扣&#xff0c;并逐渐体现出智慧化的特性。区别于传统的商业智能BI&#xff0c;智慧管理平台作为企业数字化转型的核心&#xff0c;通过信息系统的集成&#xff0c;能够对企业各个业务模块进行整合&#…

Service的双向跨进程通信

一、客户端向服务端通信。 1、创建AIDL文件&#xff0c;用于生成跨进程通信代码。 // ITestService.aidl package com.example.servicetest;interface ITestService {void sayHello(); } 2、创建服务端Service&#xff0c;添加如下代码。 public class TestService extends…

spring cloud gateway源码分析,一个请求进来的默认处理流程

1.前言 spring cloud gateway的基本组成和作用就不细赘述&#xff0c;此篇适合对此有一定了解的人阅读。 spring cloud gateway版本: Hoxton.SR1 spring cloud gateway的配置使用yml配置&#xff1a; server:port: 9527y#根据微服务名称进行动态路由的配置 spring:applicati…

elk+filebeat+kafka集群部署

EFK实验架构图&#xff1a; 实现高并发&#xff0c;无需指定logstash 3台esfile&#xff0c;3台kafka 20.0.0.10 esfile 20.0.0.20 esfile 20.0.0.30 esfile 20.0.0.11 kafka 20.0.0.12 kafka 20.0.0.13 kafka在es1主机上解压filebeat cd filebeat 安装nginx服务 vim /usr/loc…

Prometheus集群模式部署日记-主节点篇

Prometheus架构组件主节点masterPrometheus-master&#xff0c;Alertmanger&#xff0c;Grafana&#xff0c;PrometheusAlert子节点node(不同网络&#xff0c;混合云环境)Prometheus-node1 所有组件均采用docker-compose部署&#xff0c;docker 和 compose 请自行安装不再赘述…

软件开发的生命周期:从构想到维护

目录 需求分析阶段 设计阶段 实现阶段 测试阶段 部署阶段 维护阶段 结语 软件开发是一项复杂而又精密的工程&#xff0c;它的整个过程被称为软件开发生命周期。这一生命周期涵盖了从最初构想到最终维护的各个阶段&#xff0c;每个阶段都有其独特的任务和活动。在本文中&…

计算一个4+4+1的队形变换问题

2 2 1 1 2 2 2 2 1 1 2 2 3 3 A A 3 3 4 4 A 12 4 4 4 4 12 A 4 4 2 2 1 1 2 2 操场上有4个人以4a1的结构在6*6的平面上运动&#xff0c;行分布是0&#xff0c;0&#xff0c;0&#xff0c;1&#xff0c;1&#xff0c;2&#xff0c;列分布…