行是知之始,知是行之成。这篇文章主要讲述分布式|redis实现集群的几种方式你都知道了么?相关的知识,希望能为你提供帮助。
十、redis集群
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
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 = https://www.songbingjia.com/android/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所在的槽位并不归自己管理,这时候他会向客户端发送一个特殊的跳转指令携带目标操作的节点地址,告诉客户端去这个节点获取数据。
-MOVED 3999 127.0.0.1:1911
#第一个参数代表槽位,后面代表地址
迁移
【分布式|redis实现集群的几种方式你都知道了么()】
Redis迁移的单位是槽,Redis一个槽一个槽进行迁移,当一个槽正在迁移时,这个槽就处于中间过渡状态,这个槽在原节点的状态位migrating,在目标节点的状态为importing。
为什么在B请求的时候,需要先发送一个asking指令而不是直接获取key呢?
因为在迁移没有完成之前,按理说这个槽位还是不归新节点管理,如果这时候向目标节点发送该槽位的指令,节点是不认的,它会向客户端返回一个跳转到原节点的指令,如此就会造成重定向循环,ASKing指令就是打开目标节点的选项,告诉他下一条指令不能不理,而要当成自己的槽位来处理
推荐阅读
- 分享一个全网最全的订单库存扣减设计思路
- 路由基础学习笔记之OSPF建立和路由策略
- 跟着“乐哉”学习redis系列教程-Redis的订阅
- 接入第三方|接入声网灵动课堂 流程图
- 分布式|老板让我实现附近人发现的功能,我用它实现了
- 路由基础学习笔记之MPLS基本概念
- 一分钟上手SpringBootTest
- 分布式|你有了解过redis过期策略么?
- ABAP RSA方式调用银行API