Redis主从、哨兵及集群搭建

1、主从复制

目的:读写分离,主写,从读,容灾的快速恢复

主从复制原理: 
  • Slave 启动成功连接到master后会发送—个sync命令。
  • Master 接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步。
  • 全量复制:而 slave 服务在接收到数据库文件数据后,将其存盘并加载到内存中。
  • 增量复制:Master 继续将新的所有收集到的修改命令依次传给 slave,完成同步。
  • 但是只要是重新连接mater,一次完全同步(全量复制)将被自动执行。

 主节点配置:

port  6379
daemonize  yes
bind  主节点机器ip
requirepass 123456
pidfile   /var/run/redis-6379.pid
logfile   /var/log/redis/redis-6379.log
dbfilename /var/db/dump-6379.rdb
rdbcompression yes  # 指定存储到本地数据库的时候是否进行压缩

从节点配置:默认从不可写,只能读

port  6379
daemonize  yes
bind  从节点机器ip
requirepass 123456
masterauth 123456
pidfile   /var/run/redis-6380.pid
logfile   /var/log/redis/redis-6380.log
dbfilename /var/db/dump-6380.rdb
rdbcompression yes  # 指定存储到本地数据库的时候是否进行压缩
slaveof 主ip 主redis端口 #或 直接在从服务器客户端执行命令 slaveof 主ip 主redis端口

slave-priority 100 # 哨兵选举优先级,值越小,优先级越高

查看redis运行情况

# ./redis-cli -p 6379

# info replication

注意:

使用主从模式时应注意matser节点的持久化操作,matser节点在未使用持久化的情况详情下如果宕机,并自动重新拉起服务,从服务器会出现丢失数据的情况。(关掉master持久化 # CONFIG SET save 的时候)

数据丢失的原因:

因为master服务挂了之后,重启服务后,slave节点会与master节点进行一次完整的重同步操作,所以由于master节点没有持久化,就导致slave节点上的数据也会丢失掉。所以在配置了Redis的主从模式的时候,应该打开主服务器的持久化功能。

 2、哨兵模式

sentinel,哨兵是 redis 集群中非常重要的一个组件,主要有以下功能:

  • 集群监控:负责监控 redis master和 slave 进程是否正常工作。

  • 消息通知:如果某个 redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。

  • 故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。

  • 配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。

哨兵用于实现 redis 集群的高可用,本身也是分布式的,作为一个哨兵集群去运行,互相协同工作。

  • 故障转移时,判断一个 master node 是否宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举

  • 即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的

  • 哨兵通常需要3个实例,来保证自己的健壮性。

  • 哨兵+redis 主从的部署架构,是不保证数据零丢失的,只能保证 redis 集群的高可用性。

  • 对于哨兵 + redis 主从这种复杂的部署架构,尽量在测试环境和生产环境,都进行充足的测试和演练。

选择条件:

  • 优先级最高的(redis.conf中的slave-priority配置),不存在则找下一条

  • 偏移量最大的(获取主机数据最全的),不存在则找下一条

  • 选择runid最小的(每个redis实例启动后都会随机生成一个40位的runid)

配置: 

1、新建配置文件 sentinel.conf:

# 修改redis-sentinel配置文件:/etc/redis-sentinel.conf 
# 1. 绑定的地址 
bind 172.19.131.247 
# 2. 保护模式修改为否,允许远程连接 
protected-mode no 
# 3. 设定sentinel myid 每个都不一样,使用yum安装的时候,直接就生成了 
sentinel myid 04d9d3fef5508f60498ac014388571e719188527 
# 4. 设定监控地址,为对应的主redis库的内网地址 
sentinel monitor mymaster 主ip 6379 2[至少有2个哨兵同意后才进行主从切换] 
# 5. 设定5秒内没有响应,说明服务器挂了,需要将配置放在sentinel monitor master 127.0.0.1 6379 1下面 
sentinel down-after-milliseconds mymaster 5000 
# 6. 设定15秒内master没有活起来,就重新选举主 
sentinel failover-timeout mymaster 15000 
# 7. 表示如果master重新选出来后,其它slave节点能同时并行从新master同步缓存的台数有多少个,显然该值越大,所有slave节点完成同步切换的整体速度越快,但如果此时正好有人在访问这些slave,可能造成读取失败,影响面会更广。最保定的设置为1,只同一时间,只能有一台干这件事,这样其它slave还能继续服务,但是所有slave全部完成缓存更新同步的进程将变慢。 
sentinel parallel-syncs mymaster 2 
# 8. 主数据库密码,需要将配置放在sentinel monitor master 127.0.0.1 6379 1下面 
sentinel auth-pass mymaster 123456789

2、重新启动:

# 启动需要按照Master->Slave->Sentinel的顺序进行启动 
启动redis 
# 启动redis哨兵 默认端口(26379)
redis-sentinel sentinel.conf
java识别主从:
private static JedisSentinelPool jedisSentinelPool = null;

public static Jedis getJedisFromSentinel() {
    if (jedisSentinelPool == null) {
        Set sentinelSet = new HashSet<>();
        sentinelSet.add("redisIp:26379");
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(10); //最大可用连接数:
        jedisPoolConfig.setMaxIdle(5); //最大闲置连接数
        jedisPoolConfig.setMinIdle(5); //最小闲置连接数。
        jedisPoolConfig.setBlockWhenExhausted(true);//连接耗尽是否等待
        jedisPoolConfig.setMaxWaitMillis(2000); //等待时间:
        jedisPoolConfig.setTestOnBorrow(true); //取连接的时候进行一下测试 ping
        jedisSentinelPool = new JedisSentinelPool("mymaster", sentinelSet, jedisPoolConfig);
        return jedisSentinelPool.getResource();
    }
}

集群(cluster):(无中心化集群,任何一个节点都可以作为集群入口 )

解决问题:

  1. 容量扩容(分布式存储数据,启动n个节点,每个节点存储数据的1/n ,通过计算key所在的插槽-CRC16(key)%集群插槽总数,每个集群节点处理其中一部分的插槽)

  2. 并发写操作,分摊压力

 配置:

1、redis.conf

# 打开集群模式
cluster-enabled yes 
# 设置节点配置文件名
cluster-config-file nodes-6379.conf 
# 设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换
cluster-node-timeout 15000  

2、启动redis

启动完成后会生成节点对应的nodes-6379.conf文件

3、节点合并为集群(自动选择主和从)

$ cd redis安装包(不是安装目录)/src
# 执行命令
redis-cli --cluster create --cluster-replicas 1
[以最简单的方式配置集群,一主一从,三个节点] 节点1ip:端口 节点2ip:端口 节点3ip:端口 ...
# 分配原则,尽量保证每个主节点分配在不同ip上,每个主库和从库分配在不同的ip上

 4、连接

# 普通连接

$ redis-cli -p 6379

# 集群连接

$ redis-cli -c -p 6379[任何一个节点都可]

> cluster nodes  # 查看集群节点信息

5、集群操作

# 查询key的插槽值

> cluster keyslot keyName

# 计算插槽值中有几个key

> cluster countkeysinslot 12709[数值]

# 返回插槽中符合key的10个值

> cluster getkeysinslot 12709 10 

6、故障恢复 

  • 节点主机挂掉后,从机代替主机,重启主机,主机变为从机
  • 如果所有某一段插槽的主从节点都宕掉,redis 服务是否还能继续?
        如果某一段插槽的主从都挂掉,而cluster-require-full-coverage为yes,那么,整个集群都挂掉。
        如果某一段插槽的主从都挂掉,而cluster-require-full-coverage为no,那么,该插槽数据全都不能使用,也无法存储。
        redis.conf中的参数 cluster-require-full-coverage.

 7、集群jedis开发

public static void main(String[] args) {

    Setset =new HashSet();

    set.add(new HostAndPort("192.168.0.101",6379));

    JedisCluster jedisCluster = new JedisCluster(set);

    jedisCluster.set("k1", "v1");

    System.out,println(jedisCluster.get("k1"));

}

8、集群操作的不足 

  • 多键操作是不被支持的。

  • 多键的 Redis 事务是不被支持的。lua脚本不被支持。

  • 由于集群方案出现较晚,很多公司已经采用了其他的集群方案,而代理或者客户端分片的方案想要迁移至 redis cluster,需要整体迁移而不是逐步过渡,复杂度较大。

你可能感兴趣的:(Redis,redis,数据库,java)