Chinaunix首页 | 论坛 | 博客
  • 博客访问: 70295
  • 博文数量: 8
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 79
  • 用 户 组: 普通用户
  • 注册时间: 2016-09-02 10:14
文章分类

全部博文(8)

文章存档

2018年(2)

2017年(6)

我的朋友

分类: NOSQL

2017-01-10 15:03:47

一:关于redis cluster
reids-cluster计划在redis3.0中推出,可以看作者antirez的声明: (ps:跳票了好久,今年貌似加快速度了),目前的最新版本是redis3 beta2(2.9.51).
作者的目标:Redis Cluster will support up to ~1000 nodes. 赞...
目前redis支持的cluster特性(已亲测):
1):节点自动发现
2):slave->master 选举,集群容错
3):Hot resharding:在线分片
4):进群管理:cluster xxx
5):基于配置(nodes-port.conf)的集群管理
6):ASK 转向/MOVED 转向机制.

2:redis cluster 架构
1)redis-cluster

架构细节:
(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
(2)节点的fail是通过集群中超过半数的节点检测失效时才生效.
(3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
(4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value
2) redis-cluster选举:容错
(1)领着选举过程是集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster-node-timeout),认为当前master节点挂掉.
(2):什么时候整个集群不可用(cluster_state:fail),当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误
    a:如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成进群的slot映射[0-16383]不完成时进入fail状态.
    b:如果进群超过半数以上master挂掉,无论是否有slave集群进入fail状态
Redis 集群的优势:
自动分割数据到不同的节点上。 整个集群的部分节点失败或者不可达的情况下能够继续处理命令。 Redis 集群的数据分片 Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念. Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么: 节点 A 包含 0 到 5500号哈希槽. 节点 B 包含5501 到 11000 号哈希槽. 节点 C 包含11001 到 16384号哈希槽. 这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中得部分槽到D上. 如果我像移除节点A,需要将A中得槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态. Redis 集群的主从复制模型 为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品. 在我们例子中具有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用. 然而如果在集群创建的时候(或者过一段时间)我们为每个节点添加一个从节点A1,B1,C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了 不过当B和B1 都失败后,集群是不可用的. Redis 一致性保证 Redis 并不能保证数据的强一致性. 这意味这在实际中集群在特定的条件下可能会丢失写操作. 第一个原因是因为集群是用了异步复制. 写操作过程: 客户端向主节点B写入一条命令. 主节点B向客户端回复命令状态. 主节点将写操作复制给他得从节点 B1, B2 和 B3. 主节点对命令的复制工作发生在返回命令回复之后, 因为如果每次处理命令请求都需要等待复制操作完成的话, 那么主节点处理命令请求的速度将极大地降低 —— 我们必须在性能和一致性之间做出权衡。 注意:Redis 集群可能会在将来提供同步写的方法。 Redis 集群另外一种可能会丢失命令的情况是集群出现了网络分区, 并且一个客户端与至少包括一个主节点在内的少数实例被孤立。 举个例子 假设集群包含 A 、 B 、 C 、 A1 、 B1 、 C1 六个节点, 其中 A 、B 、C 为主节点, A1 、B1 、C1 为A,B,C的从节点, 还有一个客户端 Z1 假设集群中发生网络分区,那么集群可能会分为两方,大部分的一方包含节点 A 、C 、A1 、B1 和 C1 ,小部分的一方则包含节点 B 和客户端 Z1 . Z1仍然能够向主节点B中写入, 如果网络分区发生时间较短,那么集群将会继续正常运作,如果分区的时间足够让大部分的一方将B1选举为新的master,那么Z1写入B中得数据便丢失了. 注意, 在网络分裂出现期间, 客户端 Z1 可以向主节点 B 发送写命令的最大时间是有限制的, 这一时间限制称为节点超时时间(node timeout), 是 Redis 集群的一个重要的配置选项:
二:redis cluster的使用
1:安装redis cluster
1):安装redis-cluster依赖:redis-cluster的依赖库在使用时有兼容问题,在reshard时会遇到各种错误,请按指定版本安装.
(1)确保系统安装zlib,否则gem install会报(no such file to load -- zlib)

[root@node4 ~]# tar xf zlib-1.2.8.tar.gz
[root@node4 ~]# cd zlib-1.2.8
[root@node4 zlib-1.2.8]# ./configure
[root@node4 zlib-1.2.8]# make && make install
(2)安装ruby
[root@node4 ~]# tar xf ruby-2.3.1.tar.gz
[root@node4 ~]# cd ruby-2.3.1
[root@node4 ~]# ./configure --prefix=/usr/local/ruby
[root@node4 ~]# make && make install
(3)安装rubygem
[root@node4 ~]# tar xf rubygems-2.6.8.tar
[root@node4 ~]# cd rubygem-2.6.8
[root@node4 rubygems-2.6.8]# ruby setup.rb
[root@node4 rubygems-2.6.8]# cp bin/gem /usr/local/bin/
cp: overwrite `/usr/local/bin/gem'? y
(4)安装gem-redis
[root@node4 rubygems-2.6.8]# gem install redis
(5)安装 Redis
过程略
2:修改配置
1)redis配置文件结构
使用包含(include)把通用配置和特殊配置分离,方便维护.
[root@node1 etc]# mkdir -p cluster/{7000,7001,7002}
[root@node1 etc]# cp redis.conf cluster/7000/redis_7000.conf
[root@node1 etc]# cp redis.conf cluster/7001/redis_7001.conf
[root@node1 etc]# cp redis.conf cluster/7002/redis_7002.conf

以7000.conf为例修改
[root@node1 etc]# vim cluster/7000/redis_7000.conf
daemonize yes
pidfile /usr/local/redis-3.2.4/run/redis_7000.pid
port 7000
logfile /usr/local/redis-3.2.4/log/redis_7000.log
#注释掉以下信息,不需要RDB持久化 #save 900 1 #save 300 10 #save 60 10000

appendonly yes
appendfilename "appendonly_7000.aof"

#取消以下参数注释,使redis工作在集群模式下 cluster-enabled yes   #启动cluster模式 cluster-config-file nodes-7000.conf   #集群信息文件名。由redis自己维护 cluster-node-timeout 15000   #15秒联系不到对方的node,即认为对方有故障可能

#修改MAXMEMORY POLICY maxmemory-policy allkeys-lru maxmemory-samples 5
#完整redis.conf配置如下:
bind 192.168.1.104 127.0.0.1 protected-mode yes port 7000 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize yes supervised no pidfile /var/run/redis/7000.pid loglevel notice logfile "/var/log/redis/7000.log" databases 16 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump_7000.rdb dir /opt/cluster/rdb/ slave-serve-stale-data yes slave-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-disable-tcp-nodelay no slave-priority 100 maxmemory-policy allkeys-lru maxmemory-samples 5 appendonly yes appendfilename "appendonly-7000.aof" appendfsync everysec
protected-mode yes port 7000 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize yes supervised no pidfile /var/run/redis/7000.pid loglevel notice logfile "/var/log/redis/7000.log" databases 16 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump_7000.rdb dir /opt/cluster/rdb/ slave-serve-stale-data yes slave-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-disable-tcp-nodelay no slave-priority 100 maxmemory-policy allkeys-lru maxmemory-samples 5 appendonly yes appendfilename "appendonly-7000.aof" appendfsync everysec no-appendfsync-on-rewrite no
appendfilename "appendonly-7000.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes lua-time-limit 5000 cluster-enabled yes cluster-config-file /opt/cluster/nodes/nodes-7000.conf cluster-node-timeout 15000 slowlog-log-slower-than 10000 slowlog-max-len 128 latency-monitor-threshold 0 notify-keyspace-events "" hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 aof-rewrite-incremental-fsync yes
【wq】
[root@node1 redis-3.2.4]# cd /root/redis-3.2.4
[root@node1 redis-3.2.4]# cp runtest runtest-cluster runtest-sentinel /usr/local/bin
把7000修改好的配置文件cp给其他实例并修改端口
[root@node1 cluster]# cp 7000/redis_7000.conf 7003/redis_7003.conf
[root@node1 cluster]# sed -i 's/7000/7001/g' 7001/redis_7001.conf
……
[root@node1 cluster]# sed -i 's/7000/7005/g' 7005/redis_7005.conf
启动实例
[root@node1 cluster]# /usr/local/bin/redis-server /usr/local/redis-3.2.4/etc/cluster/7000/
redis_7000.conf
……
[root@node1 cluster]# /usr/local/bin/redis-server /usr/local/redis-3.2.4/etc/cluster/7005/
redis_7005.conf
修改内核参数
[root@node1 log]# vim /etc/sysctl.conf
//添加
vm.overcommit_memory = 1
或者
echo “vm.overcommit_memory = 1” >> /etc/sysctl.conf
[root@node1 log]# sysctl -p //立即生效

#从redis的启动日志及服务状态可以看出,到此redis的6个实例都已启动完成。
三、搭建redis集群
现在有了六个正在运行中的 Redis 实例, 接下来需要使用这些实例来创建集群, 并为每个节点编写配置文件。通过使用 Redis 集群命令行工具 redis-trib , 编写节点配置文件的工作可以非常容易地完成: redis-trib 位于 Redis 源码的 src 文件夹中, 它是一个 Ruby 程序, 这个程序通过向实例发送特殊命令来完成创建新集群, 检查集群, 或者对集群进行重新分片(reshared)等工作。
3.1、安装ruby环境,及安装redis的ruby依赖接口
之前已安装过……
3.2、 使用Redis 集群命令行工具 redis-trib创建集群
[root@node1 ~]# redis-trib.rb create --replicas 1 192.168.1.109:7000 192.168.1.109:7001 192.168.1.109:7002 192.168.1.109:7003 192.168.1.109:7004 192.168.1.109:7005
在最下边的箭头输入yes即可
#此过程将6个节点组成集群,3主3从
3.3、使用集群
测试 Redis 集群比较简单的办法就是使用 redis-rb-cluster 或者 redis-cli , 接下来我将使用 redis-cli 为例来进行演示:
#redis-cli 对集群的支持是非常基本的, 所以它总是依靠 Redis 集群节点来将它转向(redirect)至正确的节点。一个真正的(serious)集群客户端应该做得比这更好: 它应该用缓存记录起哈希槽与节点地址之间的映射(map), 从而直接将命令发送到正确的节点上面。这种映射只会在集群的配置出现某些修改时变化, 比如说, 在一次故障转移(failover)之后, 或者系统管理员通过添加节点或移除节点来修改了集群的布局(layout)之后, 诸如此类。
3.4、检查集群状态及验证
A。[root@node1 ~]# redis-trib.rb check 192.168.1.109:7000
选择一个节点,得到以下输出表示正常↓

B。通过客户端登陆到一个节点
[root@node1 ~]# redis-cli -c -p 7002
127.0.0.1:7002> set mykey "hello"
OK
127.0.0.1:7002> exit
再登陆到另一个节点
[root@node1 ~]# redis-cli -c -p 7005
127.0.0.1:7005> set mykey2 "hello world"
-> Redirected to slot [14119] located at 192.168.1.109:7002
OK
[root@node1 ~]# redis-cli -c -p 7003
127.0.0.1:7003> set mykey3 "welcome to beijing"
-> Redirected to slot [9990] located at 192.168.1.109:7001
OK
192.168.1.109:7001>
C。集群数据共享
[root@node1 ~]# redis-cli -c -p 7000
127.0.0.1:7000> set mykey4 "uplooking"
-> Redirected to slot [6113] located at 192.168.1.109:7001
OK
192.168.1.109:7001> get mykey2
-> Redirected to slot [14119] located at 192.168.1.109:7002
"hello world"
192.168.1.109:7002> get mykey3
-> Redirected to slot [9990] located at 192.168.1.109:7001
"welcome to beijing"
192.168.1.109:7001>
NOTE:
从上面可以看出,我实例子7000中可以访问同一个集群内的节点数据,访问的机制是根据set时分配的哈希槽,例如:在7001中,使用get mykey2,那么自动定位到7002。 

三、注意
1、主从复制
Redis集群支持主从复制功能,也就是主节点对应的从节点,但是不需要在从节点中加入slaveof :,否则会报错哦。 
2、主从配置
一般情况下,从节点的配置和对应的主节点的配置类似,但是一般从节点的大小要小于主节点的配置大小,这主要考虑内存和性能均衡方面,请在实际使用时留意下。 
3、实例通信
Redis集群中的节点实例间的数据共享机制是通过定位哈希槽(set时的键值分配的哈希),不会区分主从节点或是普通节点的通信。
<<========================================================>>
阅读(2380) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~

豆浆_tony2017-01-12 16:39:07

woaimaidong:继续努力!

好的老大

回复 | 举报

woaimaidong2017-01-12 10:51:12

继续努力!

woaimaidong2017-01-12 10:50:58