Redis之分布式搭建及使用快速入门

文章目录

        • 1、为什么需要用redis集群
        • 2、主从复制
          • a、主从复制配置
        • 3、可用性保证之哨兵机制(Sentinel)
        • 4、redis分布式方案
          • a、客户端Sharding
          • b、代理Proxy之Twemproxy
          • c、代理Proxy之Codis
          • d、Redis Cluster
          • e、分片方案总结

1、为什么需要用redis集群

老套路,性能、扩展、可用性。下面几个说法就当故事听听了。

性能

  • 第一个是因为Redis 本身的QPS已经很高了,但是如果在一些缤纷咖喱昂非常高的情况下,性能还是会受到影响。这个时候我们希望有更多的redis服务来完成工作。

扩展

  • 第二个是出于存储的考虑。因为redis所有的数据都放在内存中,如果数据量大,很容易受到硬件的限制。升级硬件收效和成本比太低,所以我们需要有一种横向扩展的方法。

可用性

  • 第三个是可用性和安全的问题了。如果只有一个redis服务,一旦服务宕机,那么所有的客户端都无法访问,会对业务造成很大的影响。另一个,如果硬件发生故障,而单机的数据无法恢复的话,带来的影响也是灾难性的。

可用性、数据安全、性能…。。。。是在编写不下去了。。。其实就几句话

  • 一台性能有限、所以只能扩展多台,扩展多台,就涉及到分布式集群问题,自然就延伸出cap理论了。就这么简单。真的是个人都喜欢去改个词 弄的千奇百怪。。哎。。
2、主从复制
a、主从复制配置

只是针对主从模式下,例如加入了sentinel 的主从关系。没有这样的中间件帮忙。自身切换很麻烦。

redis -cluster 集群模式不能使用主从复制相关命令

  • 会报错:(error) ERR REPLICAOF not allowed in cluster mode.

配置方法

  • 一种:在每个slave节点的redis.conf配置文件增加一行
    • slaveof 192.168.20.202 6379
  • 二种:启动时候通过启动参数指定master节点
    • redis-server --slaveof 192.168.20.202 6379

切换变化

  • 主从切换

    • slaveof xx xx 这样自己就变成从了
  • 主从切换的时候,这个配置会被重写成

    • # slaveof 192.168.20.202 6379
      # Generated by CONFIG REWRITE
      replicaof 192.168.20.202 6379
      
  • 查看集群状态

    • info replication
  • 断开主从复制

    • slaveof no one 此刻就断开联系了。不再复制数据
3、可用性保证之哨兵机制(Sentinel)

就是在主库故障了。重新选举主节点 ; 分别是断开连接时长、优先级排序、复制数量、进程id 来决定选举结果。Sentinel是没有主从只分,但是当redis集群master挂了,会采用Ratf算法选择一个Sentinel临时主节点去做主从切换

《快速搭建一主二从Sentinel监控配置》

功能描述:

  • 监控:Sentinel 会不断检查主服务器和从服务器是否正常运行
  • 通知:如果某一个被监控的实例出现问题,Sentinel可以通过API发出通知
  • 自动故障转移(failover):如果主服务器发生故障,Sentinel可以启动故障转移过程。把某台服务器升级为主服务器,并发出通知
  • 配置管理:客户端连接到Sentinel,获取当前的Redis主服务器的地址
4、redis分布式方案

所有客户端连接一个proxy或者用分区框架来实现数据分片(存储在不同redis服务器)

a、客户端Sharding

采用2个独立的redis 然后用Sharding来操作测试

​ 使用 ShardedJedis 之类的客户端分片代码的优势是配置简单,不依赖于其他中间
件,分区的逻辑可以自定义,比较灵活。但是基于客户端的方案,不能实现动态的服务
增减,每个客户端需要自行维护分片策略,存在重复代码。
第二种思路就是把分片的代码抽取出来,做成一个公共服务,所有的客户端都连接
到这个代理层。由代理层来实现请求和转发。

示例:

package org.example;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

import java.util.ArrayList;
import java.util.List;

@RunWith(JUnit4.class)
public class ShardingTest {

    @Test
    public void test() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();

        // redis服务器
        JedisShardInfo shardInfo1 = new JedisShardInfo("192.168.170.3", 1000);
        JedisShardInfo shardInfo2 = new JedisShardInfo("192.168.170.3", 1001);

        // 连接池
        List<JedisShardInfo> infoList = new ArrayList<>(2);
        infoList.add(shardInfo1);
        infoList.add(shardInfo2);

        ShardedJedisPool jedisPool = new ShardedJedisPool(poolConfig, infoList);

        try (ShardedJedis shardedJedis = jedisPool.getResource()) {
            for (int i = 0; i < 10000; i++) {
                shardedJedis.set("k" + i, "" + i);
            }

            for (int i = 0; i < 10000; i++) {
                shardedJedis.get("k" + i);
            }

        } catch (Exception e) {
            throw e;
        }

    }

}
b、代理Proxy之Twemproxy

twitter 开源的。two-em-proxy

比较稳定,性价比高

出现故障不能自动转移,架构复杂,需要借助其他组件(LVS/HAproxy+Keepalived)实现HA

扩缩容需要修改配置,不能实现平滑地扩缩容(需要重新分布数据)。

c、代理Proxy之Codis

国内豌豆荚开源的Codis,是一个代理中间件,由Go语言开发

codis不支持的命令:https://github.com/CodisLabs/codis/blob/release3.2/doc/unsupported_cmds.md

分片原理:Codis把所有的key分成了N个槽(例如1024),每个槽对应一个分组,一个分组对应于一个或者一组 Redis 实例。Codis 对 key 进行 CRC32 运算,得到一个32位的数字,然后模以N(槽的个数),得到余数,这个就是key对应的槽,槽后面就是Redis的实例。比如4个槽:

Codis的槽位映射关系是保存在 Proxy中的,如果要解决单点的问题,Codis 也要做集群部署, 多个Codis节点怎么同步槽和实例的关系呢?需要运行一个Zookeeper (或者etcd/本地文件)

d、Redis Cluster

3.0开始正式推出的,同时也可以实现高可用,跟Codis不一样,它是去中心化的。客户端可以连接到任意一个可用节点。

Redis既没有用哈希取模,也没有用一致性哈希,而是用虚拟槽来实现的。

Redis创建了16384个槽(slot),每个节点负责一定区间的slot。比如Node1负
责0-5460,Node2负责5461-10922,Node3负责10923-16383

注意:key与slot的关系是永远不会变的,会变的只有slot和Redis节点的关系。

《1 秒搭建Redis-Cluster集群》

  • 查看key属于那个slot

    cluster keyslot lilei
    
  • 多key操作的hash tags{}

    multi key 操作是不能跨节点的,所以要让数据分布到一个节点,就可以如下:

    # 这样{} 的标志,让他们都会落在桶一个slot里面
    set a{qs}a 1 
    set a{qs}b 1 
    set a{qs}c 1 
    set a{qs}d 1 
    set a{qs}e 1 
    
  • 客户端重定向

    在使用redis-cli时,可以加上-c参数,这样redis会自动帮我们连接到正确的节点执行命令。

    redis-cli -p 7292 -c
    
  • 数据迁移

    因为key 和slot的关系是永远不会变的,当新增了节点的时候,需要把原有的slot 分配给新的节点服务,并且把相关的数据迁移过来。

    添加新节点(新增一个7297)

    redis-cli--cluster add-node 127.0.0.1:7291 127.0.0.1:7297
    

    新增的节点没有哈希槽,不能分布数据,在原来的任意一个节点上执行:

    redis-cli--cluster reshard 127.0.0.1:7291
    
  • 高可用和主从切换原理

    当slave 发现自己的master 变为fail状态时,便尝试进行failover,以期成为新的master。由于挂掉的master可能会有多个slave从而存在多个slave竞争成为master节点的过程。

    自动实现主从角色分配,主从自动切换

    过程如下:

    1、slave发现自己的master 变为fail

    2、将自己记录的集群currentEpoch 加1,并广播FAILOVER_AUTH_REQUEST 信息

    3、其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每个epoch只发送一次ack

    4、尝试failover的slave手机FAILOVER_AUTH_ACK

    5、超过半数后变成新Master

    6、广播Pong通知其他集群节点

e、分片方案总结
功能 Codis Tewmporyx Redis Cluster
重新分片不需要重启 Yes NO Yes
pipeline Yes Yes
多key操作的hash tags{}
让命令落在同一节点
Yes Yes Yes
重新分片时的多key操作 Yes - NO
客户端支持 所有 所有 支持cluster协议的客户端

你可能感兴趣的:(•,Java架构,——【分布式缓存技术】,redis,redis集群,redis分布式,redis主从搭建)