redis 集群搭建(含SpringBoot 相关配置代码)

5 篇文章 0 订阅
2 篇文章 0 订阅

Redis常见的几种主要使用方式:

  • Redis 多副本(主从)  

 

port 6666

daemonize yes

requirepass 123

# 服务器配置masterauth作用主要是为了后期sentinel引入后重新选举master并且7000端口redis重新加入主从复制时必备的,否则会出现权限不足 

masterauth 123

slaveof 172.31.53.175 6666  (从服务器添加)

logfile ./redislog_louie.log

dir ./

#bind 192.168.250.132 127.0.0.1 #  0.0.0.0

RDB:

save 20 1  

# 自动保存策略,20秒内有一个key发生变化就自动保存

dbfilename rdb_louie.rdb  

#  rdb文件名

stop-writes-on-bgsave-error yes

 #  发生错误中断写入,建议开启

rdbcompression yes

 # 数据文件压缩,建议开启

rdbchecksum yes

 # 开启crc64错误校验,建议开启

 

AOF:

appendonly yes  

# 开启aof

appendfilename aof_louie.aof  

# aof 日志文件名

appendfsync everysec  

#  每秒记录一次日志,建议everysec

no-appendfsync-on-rewrite yes  

# 重写过程中是否向日志文件写入,yes 代表rewrite过程中,不向aof文件中追加信息,rewrite结束后再写入,no 代表rewrite执行的同时,也向aof追加信息

auto-aof-rewrite-percentage 100

# 触发重写文件增长百分比 默认100%

auto-aof-rewrite-min-size 64mb  

# 触发重写最小aof文件尺寸

../src/redis-cli -c -p 9001 -a 123 info Replication

优点特点就是主从实例间数据实时同步,并且提供数据持久化和备份策略可以实现同时对外提供服务和读写分离策略 

缺点:主节点挂掉,需要手动的晋升一个从节点作为主节点,同时需要需要业务方变更配置,主库的写能力受到单机的限制

Redis Sentinel(哨兵)

 

进入服务器的redis文件夹下,创建一个文件名为 sentinel-26379.conf 配置文件,文件内容如下

port 26379

daemonize yes

logfile "26379.log"

dir "./"

sentinel monitor mymaster 172.31.53.175 7000 2

sentinel down-after-milliseconds mymaster 30000

sentinel parallel-syncs mymaster 1

sentinel failover-timeout mymaster 15000

sentinel auth-pass mymaster 123

bind 0.0.0.0

其他的集群复制改port  即可

参数介绍:

sentinel monitor <master-name> <ip> <redis-port> <quorum>

告诉sentinel去监听地址为ip:port的一个master,这里的master-name可以自定义,quorum是一个数字,指明当有多少个sentinel认为一个master失效时,master才算真正失效

 

sentinel auth-pass <master-name> <password>

设置连接master和slave时的密码,注意的是sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应该设置相同。

 

sentinel down-after-milliseconds <master-name> <milliseconds>

这个配置项指定了需要多少失效时间,一个master才会被这个sentinel主观地认为是不可用的。 单位是毫秒,默认为30秒

 

sentinel parallel-syncs <master-name> <numslaves>

这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。

 

sentinel failover-timeout <master-name> <milliseconds>

failover-timeout 可以用在以下这些方面:     

1. 同一个sentinel对同一个master两次failover之间的间隔时间。   

2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。    

3.当想要取消一个正在进行的failover所需要的时间。    

4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了。

./redis-sentinel sentinel-port.conf        配置文件启动哨兵

 

哨兵是一个独立的进程

优点:解决上面主从的痛点,提供监控、提醒、自动故障转移三个方面的优化。

监控:通过心跳机制,不断地检查主服务器从服务器和sentinel节点 是否运作正常

提醒:当谋个服务器出现问题,Sentinel 可以通过api 像管理员发送通知。

自动故障转移:当主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中一个从服务器升级为新的主服务器, 并让其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。主服务器恢复后,就成为了一个从服务器。

 

Redis Cluster

配置文件内容为如下:其他的配置文件修改一下端口以及log文件、日志文件即可。其中中间部分cluster代表

daemonize yes

port 7000

logfile 7000.log

#masterauth 123

#requirepass 123

dir ./

bind 192.168.250.129 127.0.0.1

cluster-enabled yes

cluster-config-file nodes_7000.conf

cluster-node-timeout 15000

appendonly yes

appendfilename aof-7000.aof

appendfsync everysec

no-appendfsync-on-rewrite yes

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

工作原理

Redis 集群是一个提供在多个Redis节点间共享数据的程序集。下图以三个master节点和三个slave节点作为示例。Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽。集群的每个节点负责一部分hash槽,如图中slots所示。

 

其内部中也需要配置主从,并且内部也是采用哨兵模式,如果有半数节点发现某个异常节点,共同决定更改异常节点的状态,如果改节点是主节点,则对应的从节点自动顶替为主节点,当原先的主节点上线后,则会变为从节点。

如果集群中的master没有slave节点,则master挂掉后整个集群就会进入fail状态,因为集群的slot映射不完整。如果集群超过半数以上的master挂掉,无论是否有slave,集群都会进入fail状态。

根据官方推荐 集群部署至少要3台以上的master节点。那么接下来就开始部署吧 

 

优点:采用去中心化的思想,没有中心节点的说法自动实现负载均衡与高可用。(是主从复制和哨兵模式的结合版

解决了redis-Sentinel 主服务器的写压力 ,将主服务器做成集群,每个主节点都有从节点

方案对比,方案确定

Redis 多副本(主从):master节点宕机,没有主动的选举机制(主节点写,从节点读) 至少3台服务器

Redis-Sentinel:发现master宕机后能进行自动切换,解决一主多从master 节点宕机,写数据的问题(主备切换) 至少3台服务器

Redis-Cluster:多个主节点,减轻了主节点的压力。 至少3台服务器  (3组master - slave )

所以:这里最佳的高可用方式是官方推荐的Redis-Cluster

部署方式

  1.Sentinel节点不应该部署在一台物理机上。

    2.部署至少三个且奇数个的Sentinel节点

环境配置

第一:准备3台服务器,每台服务器运行两个redis

主机说明

主机IP

端口

Redis

172.31.53.175

7000

7001

Redis

172.31.53.175

7002

7003

Redis 

172.31.53.175

7004

7005

 

 

在每一台服务器上我们添加一下配置文件

分别为:redis-7000.conf  redis-7001.conf  redis-7002.conf  redis-7003.conf redis-7004.conf  redis-7005.conf 

配置文件内容为如下:其他的配置文件修改一下端口以及log文件、日志文件即可。其中中间部分cluster代表集群设置

daemonize yes

#masterauth 123

#requirepass 123

port 7000

logfile 7000.log

dir ./

bind 192.168.250.129 127.0.0.1

 

cluster-enabled yes

cluster-config-file nodes_7000.conf

cluster-node-timeout 15000

 

appendonly yes

appendfilename aof-7000.aof

appendfsync everysec

no-appendfsync-on-rewrite yes

auto-aof-rewrite-percentage 100

auto-aof-rewrite-min-size 64mb

上面文件都配置好后,即可启动

启动后我们就可以创建集群

注意:

在redis5.0后 创建集群统一使用redis-cli,

./src/redis-cli --cluster create 172.31.53.175:7000 172.31.53.175:7001 172.31.53.175:7002 172.31.53.175:7003 172.31.53.175:7004 172.31.53.175:7005 --cluster-replicas 1

之前的版本使用redis-trib.rb,  hostname  -i

./redis-trib.rb create --replicas 1 172.31.53.175:7000 172.31.53.175:7001 172.31.53.175:7002 172.31.53.175:7003 172.31.53.175:7004 172.31.53.175:7005

具体的可以参照redis官方网站查看
https://redis.io/topics/cluster-tutorial

创建集群命令:其中 cluster-replicas 1  代表  一个master后有几个slave,1代表为1个slave节点

 

验证一下集群是否创建成功

 

登录redis客户端 ./src/redis-cli -c -p 7000, -c 参数代表连接到集群中
我们先看一下主从配对情况,根据node ID匹配可以得出配比。如下:红色圈出来的为标注,大家可以看看是否有对应的ID,这样我们就区分了主从节点的关系了。

验证数据匹配是否采用哈希槽的方式。大家可自行测试一下。发现我在7000客户端设置的数据,被分配到7002上了。

如果是使用redis-trib.rb工具构建集群,集群构建完成前不要配置密码,集群构建完毕再通过config set + config rewrite命令逐个机器设置密码

 

客户端实现

 

Yml:

spring:
  redis:
    timeout: 60000ms
    cluster:
      max-redirects: 3
      nodes:
        - 47.105.102.123:7001
        - 47.105.102.123:7002
        - 47.105.102.123:7003
        - 47.105.102.123:7004
        - 47.105.102.123:7005
        - 47.105.102.123:7000
    lettuce:
      pool:
        max-active: 1000
        max-idle: 10
        min-idle: 5
        max-wait: -1

 

@Configuration
public class RedisConfiguration {
    @Autowired
    private RedisProperties redisProperties;
    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());
        redisClusterConfiguration.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());
        redisClusterConfiguration.setPassword(redisProperties.getPassword());
        //支持自适应集群拓扑刷新和静态刷新源
        ClusterTopologyRefreshOptions clusterTopologyRefreshOptions =  ClusterTopologyRefreshOptions.builder()
                .enablePeriodicRefresh()
                .enableAllAdaptiveRefreshTriggers()
                .refreshPeriod(Duration.ofSeconds(redisProperties.getTimeout().getSeconds()))
                .build();
        ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()
                .topologyRefreshOptions(clusterTopologyRefreshOptions).build();
        //从优先,读写分离,读从可能存在不一致,最终一致性CP
        LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder()
                .readFrom(ReadFrom.SLAVE_PREFERRED)
                .clientOptions(clusterClientOptions).build();
        return new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
    }


    @Bean
    public RedisTemplate<Object, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
//        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

备注:

<!-- lettuce客户端需要使用到 -->
<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-pool2</artifactId>
</dependency>

 

哨兵模式:客户端

spring:
  redis:
    timeout: 60000ms
    lettuce:
      pool:
        max-active: 1000
        max-idle: 10
        min-idle: 5
        max-wait: -1
    sentinel:
      master: mymaster
      nodes: 47.105.102.123:29000,47.105.102.123:29001,47.105.102.123:29002
    password: 123

server:
  port: 9999

 

@Configuration
public class RedisConfiguration {
    @Autowired
    private RedisProperties redisProperties;

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        List<RedisNode> nodes = redisProperties.getSentinel().getNodes().stream().map(e -> new RedisNode(e.split(":")[0], Integer.valueOf(e.split(":")[1])))
                .collect(Collectors.toList());
        RedisSentinelConfiguration redisClusterConfiguration = new RedisSentinelConfiguration();
        redisClusterConfiguration.setSentinels(new HashSet<>(nodes));
        redisClusterConfiguration.setPassword(redisProperties.getPassword());
        redisClusterConfiguration.setMaster(redisProperties.getSentinel().getMaster());
        //从优先,读写分离,读从可能存在不一致,最终一致性CP
        LettuceClientConfiguration lettuceClientConfiguration = LettuceClientConfiguration.builder()
                .readFrom(ReadFrom.SLAVE_PREFERRED)
                .build();
        return new LettuceConnectionFactory(redisClusterConfiguration, lettuceClientConfiguration);
    }
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
//        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

声明:部分图片及叙述借鉴自其他博友,对此表示感谢!!!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值