如何快速搭建Redis集群及理解其实现原理

2020-11-19 15:58:13 浏览数 (1)

Codis

Codis使用Go语言开发,它是一个代理中间件,和Redis一样也使用Redis协议对外提供服务,当客户端向Codis发送指令时,Codis负责将指令转发到后面的Redis实例来执行,并将结果返回给客户端

  • Codis分片原理 Codis默认将所有的key划分为1024个槽位(slot),它首先对客户端传进来的key进行crc32运算计算hash值,再将hash值对1024取模得到一个余数,这个余数就是对应的槽位 如图每个槽位都会对应多个redis实例之一,Codis在内存中维护槽位和 redis实例的映射关系。槽位默认数量是1024,它是可以设置的。
  • 不同的Codis实例之间槽位关系如何同步?Codis将槽位关系存储在zookeeper中,并且提供了一个dashboard可以用来观察和修改槽位关系,当槽位关系发生变化时,Codis Proxy会监听到变化并重新同步槽位,从而实现多个Codis proxy 之间共享相同的槽位关系。
  • java集成Codis
代码语言:javascript复制
1.安装Go环境
解压go1.14.4.linux-amd64.tar.gz 到 /usr/local
2.设置编译环境变量
export PATH=$PATH:/usr/local/go/bin
export GOPATH=/usr/local/codis/gopath
export PATH=$PATH:$GOPATH/bin
source /etc/profile(刷新环境变量)
3.下载Codis源码
mkdir -p $GOPATH/src/github.com/CodisLabs
cd $_ && git clone https://github.com/CodisLabs/codis.git -b release3.2
4.编译 Codis 源代码
cd $GOPATH/src/github.com/CodisLabs/codis
make
5.修改默认配置文件

1.修改dashboard.toml
# Set Coordinator, only accept "zookeeper" & "etcd"
coordinator_name = "zookeeper"
coordinator_addr = "127.0.0.1:2181"
# Set Codis Product {Name/Auth}.
product_name = "codis-demo"
product_auth = "123456"
# Set bind address for admin(rpc), tcp only.
admin_addr = "0.0.0.0:18080"


2.修改proxy.toml
# Set Codis Product Name/Auth.
product_name = "codis-demo"
product_auth = "123456"
# Set auth for client session
#   1. product_auth is used for auth validation among codis-dashboard,
#      codis-proxy and codis-server.
#   2. session_auth is different from product_auth, it requires clients
#      to issue AUTH <PASSWORD before processing any other commands.
session_auth = ""
# Set bind address for admin(rpc), tcp only.
admin_addr = "0.0.0.0:11080"


3.配置多个codis-server
protected-mode no
port 6379
daemonize yes
pidfile "/tmp/redis_6379.pid"
logfile "/tmp/redis_6379.log"
requirepass 123456
cp redis.conf redis-6379.conf
cp redis.conf redis-6378.conf
cp redis.conf redis-6377.conf
sed -i 's/6379/6377/g' redis-6377.conf
sed -i 's/6379/6378/g' redis-6378.conf

4.启动
_x0008_启动Codis Dashboard
nohup ../bin/codis-dashboard --ncpu=4 --config=dashboard.toml  --log=dashboard.log --log-level=WARN &
启动Codis Proxy
nohup ../bin/codis-proxy --ncpu=4 --config=proxy.toml  --log=proxy.log --log-level=WARN &
启动Codis Server
  nohup ../bin/codis-server redis-6377.conf &
  nohup ../bin/codis-server redis-6378.conf &
  nohup ../bin/codis-server redis-6379.conf &
启动Codis FE
 nohup ./bin/codis-fe --ncpu=4 --log=fe.log --log-level=WARN  --zookeeper=127.0.0.1:2181 --listen=0.0.0.0:8081 &


进入管理页面后添加proxy和server



使用jedis连接proxy
 public void testCodis(){
        // 连接池配置
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(50);
        config.setMaxIdle(50);
        config.setMinIdle(1);
        config.setMaxWaitMillis(30000);
        // 创建连接池,ip端口为codis-proxy的ip端口
        JedisPool jedisPool = new JedisPool(config, "172.16.51.127", 19000);
        // 从连接池中获取连接
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.set("foo1", "bar1");
            String value = jedis.get("foo1");
            System.out.println(value);
        }
    }

什么是Cluster ?

Redis Cluster将所有的数据划分为16384个槽,它比Codis的1024个槽位划分的还要细,每个节点负责其中一部。分槽位,槽位的信息存储于每个节点中,它不同于Codis,不需要另外的分布式存储空间来存储节点槽位信息。当Redis客户端来连接集群的时候,也会得到一份集群的槽位配置信息,这样当客户要找某个key时,可以直接定位到目标节点。这一点不同于Codis.Codis需要通过Proxy来定位目标节点,RedisCluster则直接定位。

槽位定位算法

Redis Cluster默认会对key值使用crc16算法进行hash,得到一个整数值,然后用这个整数值对16384进行取模来得到具体槽位。Redis Cluster还允许用户强制把某个key挂在特定槽位上,通过在key字符串里面嵌入tag标记,这样就可以强制把key存入到指定的槽位上

跳转

当客户端像一个错误的节点发出了指令后,该节点会发现指令的key所在的槽位并不归自己管理,这时候他会向客户端发送一个特殊的跳转指令携带目标操作的节点地址,告诉客户端去这个节点获取数据。

代码语言:javascript复制
-MOVED 3999 127.0.0.1:1911
#第一个参数代表槽位,后面代表地址

迁移

Redis迁移的单位是槽,Redis一个槽一个槽进行迁移,当一个槽正在迁移时,这个槽就处于中间过渡状态,这个槽在原节点的状态位migrating,在目标节点的状态为importing。

为什么在B请求的时候,需要先发送一个asking指令而不是直接获取key呢?因为在迁移没有完成之前,按理说这个槽位还是不归新节点管理,如果这时候向目标节点发送该槽位的指令,节点是不认的,它会向客户端返回一个跳转到原节点的指令,如此就会造成重定向循环,ASKing指令就是打开目标节点的选项,告诉他下一条指令不能不理,而要当成自己的槽位来处理

容错

Redis Cluster可以为每个主节点设置若干个从节点,当主节点发生故障的时候,集群会自动将其中某个从节点提升为主节点,如果某个主节点没有从节点,那么发生故障时,集群将会完全不可用,不过Redis提供了一个参数cluster-require-full-coverage可以允许部分节点发生故障,其他节点还可以继续对外提供服务

认真读一本书

按照惯例,文末必推一本书,这本书我也买过纸质书,本系列所有内容都是围绕本书结合自身学习进行总结归纳的。

如果需要电子版,也可以关注公众号“乐哉开讲“,后台点击“干货领取“。「当然,写书不易,条件允许的话,还请支持正版。」


作者:乐哉

0 人点赞