Redis 作为高效的缓存数据库,单机也能够表现出很好的性能。但是随着数据的增加、并发的增加,单机模式的 Redis 会受到单机性能、容量、稳定性的限制,即使 Redis 提供了稳定的持久化方案,但是单机服务器始终是部署在单个机器上,如果运行机器本身的服务器出现问题我们很难在短时间恢复服务。所以 Redis 提供了三种多机模式:
哨兵模式解决了主节点挂掉的问题,但是没有解决从节点挂掉的问题,而 redis 集群模式可以有效的解决这个问题。redis集群中的数据是和槽(slot)挂钩的,一共定义了16384个槽,所有的数据使用一致性哈希分配到不通的槽上,每个槽又根据配置分配到不同的节点上。这样就使用集群的方式让 Redis 更加高效,同时 Redis 集群中每个节点都会为其配置一个从节点,以防止节点因故障下线而导致数据不可用的问题。
集群最低需要6个节点,3主3从。我们配置6个节点的cluster-6379、cluster-6380、cluster-6381、cluster-6382、cluster-6383、cluster-6384。cluster-6379的配置文件cluster-6379.conf如下:
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize no
supervised no
pidfile /var/run/redis_6379.pid
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
slave-serve-stale-data yes
slave-read-only yes
cluster-enabled yes
cluster-config-file nodes6379.conf
cluster-node-timeout 15000
protected-mode no
appendonly yes
其他五个节点的配置只需要把 port 和 cluster-config-file 中的数字换下即可。
我们依次启动6个 Redis 服务
> $ docker run --name cluster-6379 -d -p 6379:6379 -v /Users/liushuai/Documents/dockerProject/redis/cluster-6379.conf:/etc/redis/redis.conf redis /etc/redis/redis.conf
> $ docker run --name cluster-6380 -d -p 6380:6380 -v /Users/liushuai/Documents/dockerProject/redis/cluster-6380.conf:/etc/redis/redis.conf redis /etc/redis/redis.conf
> $ docker run --name cluster-6381 -d -p 6381:6381 -v /Users/liushuai/Documents/dockerProject/redis/cluster-6381.conf:/etc/redis/redis.conf redis /etc/redis/redis.conf
> $ docker run --name cluster-6382 -d -p 6382:6382 -v /Users/liushuai/Documents/dockerProject/redis/cluster-6382.conf:/etc/redis/redis.conf redis /etc/redis/redis.conf
> $ docker run --name cluster-6383 -d -p 6383:6383 -v /Users/liushuai/Documents/dockerProject/redis/cluster-6383.conf:/etc/redis/redis.conf redis /etc/redis/redis.conf
> $ docker run --name cluster-6384 -d -p 6384:6384 -v /Users/liushuai/Documents/dockerProject/redis/cluster-6384.conf:/etc/redis/redis.conf redis /etc/redis/redis.conf
我们使用docker inspect containername查看六台服务器的IP
我们登上cluster-6379让节点握手
> $ redis-cli -h 127.0.0.1 -p 6379 [18:07:16]
127.0.0.1:6379> CLUSTER MEET 172.17.0.3 6380
OK
127.0.0.1:6379> CLUSTER MEET 172.17.0.4 6381
OK
127.0.0.1:6379> CLUSTER MEET 172.17.0.5 6382
OK
127.0.0.1:6379> CLUSTER MEET 172.17.0.6 6383
OK
127.0.0.1:6379> CLUSTER MEET 172.17.0.7 6384
OK
127.0.0.1:6379> CLUSTER NODES
b2cfa2ef5cd74f51a6d5e40159efdff376711112 172.17.0.7:6384@16384 master - 0 1540462103092 5 connected
5af7e5b30272f806a528e988b501d83366e9ad91 172.17.0.3:6380@16380 master - 0 1540462104117 1 connected
5fb1ef0852caf5d8c51b3a201d17b7b514691a13 172.17.0.4:6381@16381 master - 0 1540462105135 2 connected
67d54cd1cd9071aa5d6c4b7270a7ce12336f8168 172.17.0.2:6379@16379 myself,master - 0 1540462104000 4 connected
29da588f4e5701553751265aabd6a42ed7709cf5 172.17.0.5:6382@16382 master - 0 1540462102060 3 connected
c8ea869618205782659674b82efb2a7e29c09b2e 172.17.0.6:6383@16383 master - 0 1540462102000 0 connected
为6379、6380、6381设置槽点
cluster-slot-6379.sh
n=0
for ((i=n;i<=5461;i++));
do
redis-cli -h 127.0.0.1 -p 6379 CLUSTER ADDSLOTS $i
done
cluster-slot-6380.sh
n=5462
for ((i=n;i<=10922;i++));
do
redis-cli -h 127.0.0.1 -p 6380 CLUSTER ADDSLOTS $i
done
cluster-slot-6381.sh
n=10923
for ((i=n;i<=16383;i++));
do
redis-cli -h 127.0.0.1 -p 6381 CLUSTER ADDSLOTS $i
done
执行完3个脚本后,在任意一台Redis服务器上查看slots信息
127.0.0.1:6379> CLUSTER SLOTS
1) 1) (integer) 5462
2) (integer) 10922
3) 1) "172.17.0.3"
2) (integer) 6380
3) "5af7e5b30272f806a528e988b501d83366e9ad91"
2) 1) (integer) 10923
2) (integer) 16383
3) 1) "172.17.0.4"
2) (integer) 6381
3) "5fb1ef0852caf5d8c51b3a201d17b7b514691a13"
3) 1) (integer) 0
2) (integer) 5461
3) 1) "172.17.0.2"
2) (integer) 6379
3) "67d54cd1cd9071aa5d6c4b7270a7ce12336f8168"
把剩余的3台服务器分别设为有槽点服务器的备用节点
$ redis-cli -h 127.0.0.1 -p 6382 CLUSTER REPLICATE 67d54cd1cd9071aa5d6c4b7270a7ce12336f8168
$ redis-cli -h 127.0.0.1 -p 6383 CLUSTER REPLICATE 5af7e5b30272f806a528e988b501d83366e9ad91
$ redis-cli -h 127.0.0.1 -p 6384 CLUSTER REPLICATE 5fb1ef0852caf5d8c51b3a201d17b7b514691a13
我们在任何一台Redis服务器上查看集群信息
127.0.0.1:6379> CLUSTER NODES
b2cfa2ef5cd74f51a6d5e40159efdff376711112 172.17.0.7:6384@16384 slave 5fb1ef0852caf5d8c51b3a201d17b7b514691a13 0 1540463049250 5 connected
5af7e5b30272f806a528e988b501d83366e9ad91 172.17.0.3:6380@16380 master - 0 1540463049000 1 connected 5462-10922
5fb1ef0852caf5d8c51b3a201d17b7b514691a13 172.17.0.4:6381@16381 master - 0 1540463050282 2 connected 10923-16383
67d54cd1cd9071aa5d6c4b7270a7ce12336f8168 172.17.0.2:6379@16379 myself,master - 0 1540463049000 4 connected 0-5461
29da588f4e5701553751265aabd6a42ed7709cf5 172.17.0.5:6382@16382 slave 67d54cd1cd9071aa5d6c4b7270a7ce12336f8168 0 1540463047000 4 connected
c8ea869618205782659674b82efb2a7e29c09b2e 172.17.0.6:6383@16383 slave 5af7e5b30272f806a528e988b501d83366e9ad91 0 1540463049000 1 connected
集群搭建完毕
cluster-6379为主节点,其从节点为cluster-6382。我们停掉cluster-6379
docker stop cluster-6379
查看集群信息
127.0.0.1:6380> CLUSTER NODES
b2cfa2ef5cd74f51a6d5e40159efdff376711112 172.17.0.7:6384@16384 slave 5fb1ef0852caf5d8c51b3a201d17b7b514691a13 0 1540463465561 5 connected
5af7e5b30272f806a528e988b501d83366e9ad91 172.17.0.3:6380@16380 myself,master - 0 1540463463000 1 connected 5462-10922
67d54cd1cd9071aa5d6c4b7270a7ce12336f8168 172.17.0.2:6379@16379 master,fail - 1540463424976 1540463424000 4 connected
29da588f4e5701553751265aabd6a42ed7709cf5 172.17.0.5:6382@16382 master - 0 1540463464534 6 connected 0-5461
c8ea869618205782659674b82efb2a7e29c09b2e 172.17.0.6:6383@16383 slave 5af7e5b30272f806a528e988b501d83366e9ad91 0 1540463464000 1 connected
5fb1ef0852caf5d8c51b3a201d17b7b514691a13 172.17.0.4:6381@16381 master - 0 1540463462000 2 connected 10923-16383
可以看到6379处于宕机状态,而6382变成了主节点。我们再回复6379并查看集群信息
$ docker start cluster-6379
127.0.0.1:6380> CLUSTER NODES
b2cfa2ef5cd74f51a6d5e40159efdff376711112 172.17.0.7:6384@16384 slave 5fb1ef0852caf5d8c51b3a201d17b7b514691a13 0 1540463556698 5 connected
5af7e5b30272f806a528e988b501d83366e9ad91 172.17.0.3:6380@16380 myself,master - 0 1540463554000 1 connected 5462-10922
67d54cd1cd9071aa5d6c4b7270a7ce12336f8168 172.17.0.2:6379@16379 slave 29da588f4e5701553751265aabd6a42ed7709cf5 0 1540463558733 6 connected
29da588f4e5701553751265aabd6a42ed7709cf5 172.17.0.5:6382@16382 master - 0 1540463554000 6 connected 0-5461
c8ea869618205782659674b82efb2a7e29c09b2e 172.17.0.6:6383@16383 slave 5af7e5b30272f806a528e988b501d83366e9ad91 0 1540463557000 1 connected
5fb1ef0852caf5d8c51b3a201d17b7b514691a13 172.17.0.4:6381@16381 master - 0 1540463557715 2 connected 10923-16383
可以看到6379变成了从节点。
非著名程序员,全栈开发工程师,长期专注系统开发与架构设计。
功能待开通!
redis 的 string 类型是支持过期设置的,默认是永不过期的。 Redis 设置过期 redis 中设置设置 key 过期有3中方式 第一种在设置值的时候指定过期时间 Set 命令格式 SET key value [EX seconds] [PX milliseconds] [NX|XX] EX second :设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。 PX millisecond :设置键的过期时间为 millisecond 毫秒。 3. SET key value PX m
Redis 作为高效的缓存数据库,单机也能够表现出很好的性能。但是随着数据的增加、并发的增加,单机模式的 Redis 会受到单机性能、容量、稳定性的限制,即使 Redis 提供了稳定的持久化方案,但是单机服务器始终是部署在单个机器上,如果运行机器本身的服务器出现问题我们很难在短时间恢复服务。所以 Redis 提供了三种多机模式: 主从复制模式 哨兵模式 集群模式 哨兵模式 主从复制模式解决了数据备份和单机可能存在的性能问题,但是也引入了新的问题,一主多从,在使用过程中,如果主服务器挂掉那么整个 Redis 服务的写就挂掉了,如果一个从服务器挂掉那么调用方就无法正确的读数据了,只能通过修改调
redis 中内存管理没有直接使用 C 语言提供的方法而是做了一个可管理已分配内存大小及添加了自己分配策略的实现,下面从 SDS 开始去了解 redis 的内存管理实现及策略。 SDS 内存管理函数定义如下: src/sdsalloc.h #include "zmalloc.h" #define s_malloc zmalloc #define s_realloc zrealloc #define s_free zfree s_malloc 内存申请、s_realloc 内存重新分配、s_free 内存释放,这里定义分别是 zmalloc.h 里三个函数的别名,而 zmalloc zrea
有时候我们需要在短时间内往 redis 里插入大量的数据,我们如果单条单条的出入会浪费很多时间和服务器资源,我们可以使用管道来实现快速的插入。 netcat 我们把需要插入 redis 的数据创建为如下的一个命令集文件 set key1 val1 set key2 val2 ... set key3 val3 我们使用如下命令执行数据导入 > $ cat /tmp/test|nc localhost 6379 +OK +OK +OK pipe mode 使用 netcat 并不是一个可靠地方式,因为用netcat进行大规模插入时不能检查错误。从Redis 2.6开始redis-cli支
在面试过程中只要涉及到 Redis,一定会问到 Redis是多进程还是多线程?为什么单线程还可以有这么高的性能? Redis为什么是单线程的 Redis 是基于内存的操作,CPU 不是 Redis 的瓶颈,Redis 的瓶颈最有可能是机器的内存的大小和网络的带宽,而且单线程的性能已经非常高了,就没有必要使用多线程了,所以 Redis 是单进程单线程的。 提示: 如果我们运行的服务器是多核服务器,为了充分利用多核优势我们可以在单台服务器起多个 Redis 服务,或者架设 主从复制、哨兵模式、集群模式等多机方案。 Redis 服务运行时只是处理客户端请求是单进程单线程的,但是服务运行时会有其他进