redis集群

Redis集群

Redis 集群:实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N。

Redis 集群通过分区来提供一定程度的可用性 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求

 

数据分片(将数据分给不同的redis服务器)

(1)客户端实现数据分片
客户端自己计算数据的key应该在哪个机器上存储和查找,此方法的好处是降低了服务器集群的复杂度,客户端实现数据分片时,服务器是独立的,服务器之前没有任何关联。多数redis客户端库实现了此功能,也叫sharding,这种方式的缺点是客户端需要实时知道当前集群节点的联系信息,同时,当添加一个新的节点时,客户端要支持动态sharding.,多数客户端实现不支持此功能,需要重启redis。另一个弊端是redis的HA(高可用性)需要额外考虑。

 

(2)服务器实现数据分片
其理论是,客户端随意与集群中的任何节点通信,服务器端负责计算某个key在哪个机器上,当客户端访问某台机器时,服务器计算对应的key应该存储在哪个机器,然后把结果返回给客户端,客户端再去对应的节点操作key,是一个重定向的过程,此方式是redis3.0正在实现,目前处于beta版本, Redis 3.0的集群同时支持HA功能,某个master节点挂了后,其slave会自动接管。

 

(3)通过代理服务器实现数据分片
此方式是借助一个代理服务器实现数据分片,客户端直接与proxy联系,proxy计算集群节点信息,并把请求发送到对应的集群节点。降低了客户端的复杂度,需要proxy收集集群节点信息。Twemproxy是twitter开源的,实现这一功能的proxy。这个实现方式在客户端和服务器之间加了一个proxy,但这是在redis 3.0稳定版本出来之前官方推荐的方式。结合redis-sentinel的HA方案,是个不错的组合

 

Redis 集群提供了以下好处

实现扩容,分摊压力,无中心配置相对简单

 

Redis 集群的不足

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

 

问题

容量不够,redis如何进行扩容?

并发写操作, redis如何分摊?

另外,主从模式,薪火相传模式,主机宕机,导致ip地址发生变化,应用程序中配置需要修改对应的主机地址、端口等信息。

解决

添加多个主机同时进行写操作

之前通过代理主机来解决,但是redis3.0中提供了解决方案。就是无中心化集群配置

 

 代理主机

 

 

 

无中心化集群配置

 

 

 

某一个主机挂掉后,之后从机补上空位,主机重启为从机(和哨兵模式一样

 

 

 

 

 

 

先删除持久化文件(*为匹配通配符,dump63*代表前缀带dump63的文件

rm -rf dump63*

创建配置文件(开启集群模式)(制作6个实例,6379,6380,6381,6389,6390,6391

#引用原redis.conf
include /etc/redis.conf
#Pid文件名字pidfile(后台运行时写入pid的文件)
pidfile /var/run/redis_6391.pid
#开启daemonize yes(守护线程 即后台运行)
daemonize yes
#dump.rdb名字dbfilename
dbfilename dump6391.rdb
#30秒中有5个key修改了就进行持久化
save 30 5
#设置自己redis的密码
requirepass 123456
#给从机设置主机的密码
masterauth 123456
#指定端口port
port 6391
#打开集群模式
cluster-enabled yes
#设定节点配置文件名
cluster-config-file nodes-6391.conf
#设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换。
cluster-node-timeout 15000
#设置某块主从都挂掉,是否挂掉整个集群(默认为no  某块主从的使用不了,其他的可以用)
#cluster-require-full-coverage yes

 

启动6个redis服务实例(重新启动节点时必须要先进入redis中    cd /myredis)

redis-server /myredis/redis6379.conf 

redis-server /myredis/redis6380.conf

redis-server /myredis/redis6381.conf

redis-server /myredis/redis6389.conf

redis-server /myredis/redis6390.conf

redis-server /myredis/redis6391.conf

 

查看redis进程状态

ps -ef | grep redis

 

开放端口(需要防火墙开放6379到6391端口,以及redis总线(前面端口+10000):16379到16391:)

/sbin/iptables -I INPUT -p tcp --dport 6379:6381 -j ACCEPT

/sbin/iptables -I INPUT -p tcp --dport 6389:6391 -j ACCEPT

/sbin/iptables -I INPUT -p tcp --dport 16379:16381 -j ACCEPT

/sbin/iptables -I INPUT -p tcp --dport 16389:16391 -j ACCEPT

备注:关闭端口(将ACCEPT 换为 DROP)

 

 

将六个节点合成一个集群

组合之前,请确保所有redis实例启动后,nodes-xxxx.conf文件都生成正常。

跳转位置(需要先查看redis文件夹名称)

cd  /opt/redis-6.2.5/src

合成集群(-a后的123456是密码          --cluster-replicas后的1为 主机和从机比例为1:1(ip必须使用真实的公网ip地址(使用云服务器情况)   后面ip不能为127.0.0.1        6381端口为主机对应6389端口从机,切两半对应最近的))

redis-cli -a 123456 --cluster create --cluster-replicas 1 112.126.246.5:6379 112.126.246.5:6380 112.126.246.5:6381 112.126.246.5:6389 112.126.246.5:6390 112.126.246.5:6391

成功后

 

普通方式登录redis-cli -p 6379

可能直接进入读主机,存储数据时,会出现MOVED重定向操作。所以,应该以集群方式登录

进入集群操作(多了-c   需要-a添加密码,跳转后放入数据不会报没有权限)

redis-cli -c -p 6379 -a 123456 

查看节点状态

cluster nodes

 

放入一条数据(使用key来计算插槽)(不能同时添加多个key(计算不了插槽),需要使用组)

set k1 v1

放入几条数据(使用一个组  {xxx}  来计算插槽(   例如:user   ))

mset name{user} lucy age{user} 20

 

查询集群中的key(5474:插槽值,    1:返回key的数量)

cluster getkeysinslot 5474 1

计算key对应的插槽值(不需要已放入值)

cluster keyslot user

查询已进入主机中的插槽对应有几个值(不能查询已进入插槽范围外的)

cluster countkeysinslot 5474

  

public class RedisCluster {
    public static void main(String[] args){

        JedisPoolConfig config = new JedisPoolConfig();
        config .setMaxTotal(500);
        config .setMinIdle(2);
        config .setMaxIdle(500);
        config .setMaxWaitMillis(10000);
        config .setTestOnBorrow(true);
        config .setTestOnReturn(true);
        //创建对象
        Set<HostAndPort> nodes = new HashSet<HostAndPort>();
        nodes.add(new HostAndPort("112.126.246.5", 6379));
        nodes.add(new HostAndPort("112.126.246.5", 6380));
        nodes.add(new HostAndPort("112.126.246.5", 6381));
        nodes.add(new HostAndPort("112.126.246.5", 6389));
        nodes.add(new HostAndPort("112.126.246.5", 6390));
        nodes.add(new HostAndPort("112.126.246.5", 6391));
        JedisCluster jedisCluster = new JedisCluster(nodes, 10000, 10000, 100, "123456", config);

        //进行操作
        jedisCluster.set("b1","value");
        String value = jedisCluster.get("b1");
        System.out.println(value);

        jedisCluster.close();
    }
}
简单的使用RedisCluster连接集群

 

集群使用插槽将数据平均分配到不同的主机上(计算方式和hash算法相似)

一个 Redis 集群包含 16384 个插槽(hash slot), 数据库中的每个键都属于这 16384 个插槽的其中一个,

集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。

集群中的每个节点负责处理一部分插槽。 举个例子, 如果一个集群可以有主节点, 其中:

节点 A 负责处理 0 号至 5460 号插槽。

节点 B 负责处理 5461 号至 10922 号插槽。

节点 C 负责处理 10923 号至 16383 号插槽。

当放入值时会计算键或者组插槽值,根据插槽范围决定切换到那台主机的redis中进行放入值的操作

 

 

posted @ 2021-08-09 18:40  低调的。。。  阅读(128)  评论(0编辑  收藏  举报