redis集群之REDIS CLUSTER

摘要:
RedisCluster命令行//集群CLUSTERINFO打印集群的信息CLUSTERNODES列出集群当前已知的所有节点,以及这些节点的相关信息。CLUSTERREPLICATE将当前节点设置为node_id指定的节点的从节点。CLUSTERSAVECONFIG将节点的配置文件保存到硬盘里面。CLUSTERFLUSHSLOTS移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。CLUSTERSETSLOTSTABLE取消对槽slot的导入或者迁移。//键CLUSTERKEYSLOT计算键key应该被放置在哪个槽上。CLUSTERCOUNTKEYSINSLOT返回槽slot目前包含的键值对数量。CLUSTERGETKEYSINSLOT返回count个slot槽中的键。
1. Linux系统配置

1.1. vm.overcommit_memory设置

overcommit_memory文件指定了内核针对内存分配的策略,其值可以是0、1、2。

0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2, 表示内核允许分配超过所有物理内存和交换空间总和的内存

jenkins_service@jenkinsservice:~/redis-3.0.1$ sudo sysctl vm.overcommit_memory=1

vm.overcommit_memory = 1

1.2. Transparent Huge Pages开启

THP(Transparent Huge Pages)是一个使管理Huge Pages自动化的抽象层。

目前需要注意的是,由于实现方式问题,THP会造成内存锁影响性能,尤其是在程序不是专门为大内内存页开发的时候,简单介绍如下:

操作系统后台有一个叫做khugepaged的进程,它会一直扫描所有进程占用的内存,在可能的情况下会把4kpage交换为Huge Pages,在这个过程中,对于操作的内存的各种分配活动都需要各种内存锁,直接影响程序的内存访问性能,并且,这个过程对于应用是透明的,在应用层面不可控制,对于专门为4k page优化的程序来说,可能会造成随机的性能下降现象。

Redis Cluster 命令行

//集群(cluster)

  1. CLUSTERINFO打印集群的信息
  2. CLUSTERNODES列出集群当前已知的所有节点(node),以及这些节点的相关信息。
  3. //节点(node)
  4. CLUSTERMEET<ip><port>将ip和port所指定的节点添加到集群当中,让它成为集群的一份子。
  5. CLUSTERFORGET<node_id>从集群中移除node_id指定的节点。
  6. CLUSTERREPLICATE<node_id>将当前节点设置为node_id指定的节点的从节点。
  7. CLUSTERSAVECONFIG将节点的配置文件保存到硬盘里面。
  8. //槽(slot)
  9. CLUSTERADDSLOTS<slot>[slot...]将一个或多个槽(slot)指派(assign)给当前节点。
  10. CLUSTERDELSLOTS<slot>[slot...]移除一个或多个槽对当前节点的指派。
  11. CLUSTERFLUSHSLOTS移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
  12. CLUSTERSETSLOT<slot>NODE<node_id>将槽slot指派给node_id指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
  13. CLUSTERSETSLOT<slot>MIGRATING<node_id>将本节点的槽slot迁移到node_id指定的节点中。
  14. CLUSTERSETSLOT<slot>IMPORTING<node_id>从node_id指定的节点中导入槽slot到本节点。
  15. CLUSTERSETSLOT<slot>STABLE取消对槽slot的导入(import)或者迁移(migrate)。
  16. //键(key)
  17. CLUSTERKEYSLOT<key>计算键key应该被放置在哪个槽上。
  18. CLUSTERCOUNTKEYSINSLOT<slot>返回槽slot目前包含的键值对数量。
  19. CLUSTERGETKEYSINSLOT<slot><count>返回count个slot槽中的键。


2. 配置文件

开启cluster的redis必须是空服务器

修改redis.conf开启cluster

redis集群之REDIS CLUSTER第1张

设置3个cluster

10.24.6.7:6379

10.24.6.4:6379

10.24.6.6:6379

3. 查看初始redis集群状态

启动三个节点上的Redis服务器。此时,三个Redis服务器节点均会以Redis Cluster的方式开始运行,但并没有自动构建集群,因为三者还处于“我不认识你,你不属于我”的状态,它们每个都是孤零零的Redis节点,或者是只包含了一个节点的集群。我们可以通过Redis客户端连接到服务器查看它们的状态,图一给出了状态查询方法和查询结果,其中cluster nodes命令用于查看当前Redis节点所属的Redis集群中的所有节点,而cluster info则用于查看当前Redis节点所属的Redis集群的整体状态。由图中我们可以看到,Redis集群中仅包含一个Redis节点,也就是当前节点,整个集群的状态是fail。

redis集群之REDIS CLUSTER第2张


4. 分配hash slot

通过上面的操作,我们已经将三个各自为政的Redis节点规划到一个相同的集群中,那么我们现在是否就已经完成了集群搭建的所有工作了呢?非也!通过图二中对集群状态的查看我们可以知道,当前集群的状态还是fail,此时的Redis集群是不工作的,无法处理任何Redis命令。那么集群的状态为什么还是fail呢?本博主通过查看官方文档说明找到了原因所在,现摘录原文如下:

The FAIL state for the cluster happens in two cases.

1) If at least one hash slot is not served as the node serving it currently is in FAIL state.

2) If we are not able to reach the majority of masters (that is, if the majorify of masters are simply in PFAIL state, it is enough for the node to enter FAIL mode).

很明显,导致我们的集群处于fail状态的原因不是第二个条,也就是说至少有一个hash slot没有被服务!稍微考虑一下,可不是!何止有一个hash slot没有被服务,压根儿就没有Redis节点为任何hash slot服务!众所周知,Redis Cluster通过hash slot将数据根据主键来分区,所以一条key-value数据会根据算法自动映射到一个hash slot,但是一个hash slot存储在哪个Redis节点上并不是自动映射的,是需要集群管理者自行分配的。那么我们需要为多少个hash slot分配Redis节点呢?根据源码可知是16384个,即我们要将16384个hash slot分配到集群内的三个节点上。Redis中用于分配hash slot的命令有很多,其中包括cluster addslots、cluster delslots和cluster setslot。鉴于我们现在是集群的初始化阶段,所以我们可以选择cluster addslots来分配hash slot,该命令的语法为clusteraddslotsslot1 [slot2] ... [slotN]。

4.1. nodes-6379.conf分配

每个redis客户端单独分配自己负责的部分

修改内容如下:cda76a0a094d2ce624e33bed7f3c75689a4128fd :0 myself,master - 0 0 connected0-5000(注意是在自身节点的描述,也就是包含了myself那一行的后面追加hash slot的范围)。类似的,Redis Cluster Node2上nodes-6379.conf文件中追加5001-10000,Redis Cluster Node3上nodes-6379.conf文件中追加10001-16383。经过这样的配置后,Redis Cluster Node1负责存储0至5000之间的所有hash slots,Redis Cluster Node2负责存储5001至10000之间的所有hash slots,Redis Cluster Node3负责存储10001至16383的所有hash slots。

redis集群之REDIS CLUSTER第3张

4.2. Redis cluster 命令分配

redis集群之REDIS CLUSTER第4张

5. 搭建Redis集群

这里所谓的搭建集群,说白了就是让之前启动的三个Redis节点彼此连通,意识到彼此的存在,那么如何做到这一点呢?答案就是cluster meet命令。该命令的作用就是将当前节点主动介绍给另外一个节点认识,图二给出了cluster meet命令的执行方法和执行效果,由图中可知我们使用cluster meet命令分别将Redis Cluster Node1介绍给了Redis Cluster Node2(节点IP地址为192.168.32.3,运行端口为6379)和Redis Cluster Node3(节点IP地址为192.168.32.4,运行端口为6379),之后我们再次查看集群节点和集群状态就可以知道,三个节点已经成功合并到了同一个集群中。

redis集群之REDIS CLUSTER第5张

这里找到了3个节点

查看10.24.6.6客户端

redis集群之REDIS CLUSTER第6张

至此,3个结点

redis集群之REDIS CLUSTER第7张

搭建完成标识:

redis集群之REDIS CLUSTER第8张

在集群状态显示为ok之后,我们就可以像在Redis单机版上一样执行Redis命令了。


6. 测试

6.1. 非集群模式

6.1.1. Redis-cli

redis集群之REDIS CLUSTER第9张

redis集群之REDIS CLUSTER第10张

非集群模式客户端在cluster跳转时会提示MOVED错误

6.1.2. Redis客户端库

from redis.sentinel import Sentinel
sentinel = Sentinel([(
'10.24.6.7', 26379)], socket_timeout=0.1)
master = sentinel.master_for(
'10.24.6.5master', socket_timeout=0.1)
print master
master.set(
'aaaaaaaaaaaaaaa', 'bar')
master.set(
'bbbbbbbbbbbbbbbb', 'bar')
print master.get('aaaaaaaaaaaaaaa')
print master.get('bbbbbbbbbbbbbbbb')

Traceback (most recent call last):

File "E:/HomeInternet/server/utest_workspace/utest_utils/utest_unit/__init__.py", line 23, in <module>

master.set('bbbbbbbbbbbbbbbb', 'bar')

File "builddist.win32egg edisclient.py", line 1055, in set

File "builddist.win32egg edisclient.py", line 565, in execute_command

File "builddist.win32egg edisclient.py", line 577, in parse_response

File "builddist.win32egg edissentinel.py", line 55, in read_response

File "builddist.win32egg edisconnection.py", line 574, in read_response

redis.exceptions.ResponseError: MOVED 9577 10.24.6.6:6379

6.2. 集群模式(-C)

6.2.1. Redis-cli

redis集群之REDIS CLUSTER第11张

集群模式客户端在跳转时会自动进行结点转向

6.2.2. Redis Cluster

https://github.com/Grokzen/redis-py-cluster

from rediscluster import StrictRedisCluster
startup_nodes = [{
"host": "10.24.6.7", "port": "6379"}]
rc = StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True)
print rc.set("bbbbbbbbbbbbbbbb", "bar")
True
print rc.get("bbbbbbbbbbbbbbbb")

redis集群之REDIS CLUSTER第12张

6.2.3. Redis Sentinel + Cluster

from redis.sentinel import Sentinel
from redisclusterimport StrictRedisCluster
sentinel = Sentinel([(
'10.24.6.7', 26379)], socket_timeout=0.1)
ip, port = sentinel.discover_master(
'10.24.6.5master')
rc = StrictRedisCluster(host=ip, port=port, decode_responses=True)
print rc.set("bbbbbbbbbbbbbbbb", "bar")
print rc.get("bbbbbbbbbbbbbbbb")

redis集群之REDIS CLUSTER第13张

免责声明:文章转载自《redis集群之REDIS CLUSTER》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇FPGA之资源优化思想的运用Python获取IAccessible接口下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Golang操作Redis

redis 简介 redis(REmote DIctionary Server)是一个由Salvatore Sanfilippo写key-value存储系统,它由C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value类型的数据库,并提供多种语言的API。和Memcached类似,它支持存储的value类型相对更多,包括str...

nodejs中Buffer的创建和转换

  buffer是用来做什么?主要是用来处理二进制文件流和TCP流的文件缓存区。我们可以将二进制流和string,json,int进行转换,也可以进行复制,或者通过自带的函数进行判断buffer的一些状态。   创建Buffer对象(实例)     1.使用var buffer = new Buffer(size)创建对象,然后用buffer.fill(v...

redis自定义RedisCacheManager

1.redis自定义配置 package com.meritdata.cloud.shellmiddleplatform.dataservice.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.P...

使用 Consul + Docker + Registrator + Consul-template 搭建可伸缩服务发现平台

背景介绍 Docker 的出现,改变了软件的交付方式,使得开发、测试、运维都能在一个完全统一的环境中进行。在服务容器化的网络中,需要添加服务发现功能。每个服务可能对应多个示例以容器运行在多个机器上,并且提供自动注册和失败检测机制。目前服务发现已经有很多成熟的解决方案,例如 Spring Cloud中的 Eureka 注册中心,Hystrix 断路器,zuu...

Redis开启AOF导致的删库事件

事件背景 Redis主从开启AOF,错误操作导致数据被清空。 Redis主要作用:缓存、队列。 事故过程 Redis搭建了主从,持久化方式为RDB,RDB没有定时备份,且AOF都没有开启。 考虑到开启AOF会使Redis安全性更高,所以尝试先在从机做测试,没问题后再上主机。 Redis开启AOF的方式非常简单,打开Redis的conf文件,找到【appe...

vss安装,设置以及与vs2005联合项目操作(转) 子曰

服务端安装 1.安装Microsoft Visual SourceSafe2005到一台服务器,安装模式选择Full 2.运行Microsoft Visual SourceSafe Administration 3.建立一个新的数据库,记住数据库所在目录,并将之设置为共享,权限为完全控制 4.添加新用户 客户端安装 5.在本地机器安装Microsoft...