redis

分布式系统基础

ACID,是指数据库管理系统(DBMS)在写入或更新资料的过程中,为保证事务(transaction)是正确可靠的,所必须具备的四个特性:原子性(atomicity,或称不可分割性)、一致性(consistency)、隔离性(isolation,又称独立性)、持久性(durability)。

CAP理论
在理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer’s theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点:

  • 一致性(Consistency) (等同于所有节点访问同一份最新的数据副本)
  • 可用性(Availability)(每次请求都能获取到非错的响应——但是不保证获取的数据为最新数据)
  • 分区容错性(Partition tolerance)(以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择[3]。)
    根据定理,分布式系统只能满足三项中的两项而不可能满足全部三项[4]。理解CAP理论的最简单方式是想象两个节点分处分区两侧。允许至少一个节点更新状态会导致数据不一致,即丧失了C性质。如果为了保证数据一致性,将分区一侧的节点设置为不可用,那么又丧失了A性质。除非两个节点可以互相通信,才能既保证C又保证A,这又会导致丧失P性质。

BASE是指基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency)。

数据分类:结构化数据,半结构化数据,非结构化数据。

redis

全称:Remote Directory Server

redis配置文件详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
######### NETWORK ########## 网络相关的配置
port 6379
bind 0.0.0.0 监听地址,0.0.0.0表示监听本机所有地址的6379端口
protected-mode yes 是否启动保护模式
port 6379 监听端口
tcp-backlog 511 后援队列长度
timeout 300 超时时间
tcp-keepaive 300 tcp连接的超时时间
########## SECURITY ######### 安全相关的配置
requirepass msq 登录密码,设置密码后,登录到redis上之后,需要先使用auth password 进行认证后才可以使用redis。
########### LIMITS ########## 资源限制相关的设置
maxclients 10000 最大并发连接数
maxmemory <bytes> 最大内存使用量,以字节为单位。
maxmemory-policy noeviction
淘汰策略:volatile-lru, allkeys-lru, volatile-random, allkeys-random, volatile-ttl, noeviction
maxmemory-samples 5
淘汰算法运行时的采样样本数;

redis数据持久化

redis主从复制

配置从服务器指向主服务器

1
2
3
4
5
6
~]# vi /etc/redis.conf
bind 0.0.0.0
slaveof 192.168.34.103 6379
masterauth msq
slave-read-only yes
slave-serve-stale-data yes #从节点是否可以使用过期的数据

主服务器只需绑定能够连接到从服务器的网卡上即可。

也可以在从服务器上直接配置以命令行的方式配置主从服务器,如下

1
2
3
127.0.0.1:6379> SLAVEOF host port
127.0.0.1:6379> CONFIG SET masterauth msq
127.0.0.1:6379> CONFIG REWRITE #将配置写入到配置文件中,

在redis内部设置密码

1
2
3
127.0.0.1:6379> config set requirepass msq
127.0.0.1:6379> auth msq
127.0.0.1:6379> config rewrite

redis sentinel

redis sentinel主要有三个功能:监控,通知,自动故障转移
配置redis-sentinel,所有节点的sentinel配置应该保持一模一样。

1
2
3
4
5
6
7
8
9
10
[root@node02 ~]# grep "^[a-Z]" /etc/redis-sentinel.conf 
port 26379
bind 0.0.0.0 #最好设置bind
dir /tmp
sentinel monitor mymaster 192.168.34.103 6379 2 #设定主从集群的名称为mymaster,master的ip为192.168.34.103,端口为6379,至少需要有2个sentinel节点同时判定主节点故障时,才认为其真的故障。
sentinel auth-pass mymaster msq #口令
sentinel down-after-milliseconds mymaster 5000 #监控到指定的鸡群主节点异常状态持续多久才将其标记为故障。
sentinel parallel-syncs mymaster 2 #指在failover过程中,能够被sentinel并行配置的从节点的数量。
sentinel failover-timeout mymaster 180000 #sentinel必须在指定的时长内完成故障转移操作,否则将视故障转移操作失败。
logfile /var/log/redis/sentinel.log

启动redis-sentinel

1
[root@node02 ~]# systemctl start redis-sentinel

此时,redis-sentinel会自动获取所有节点的状态

1
2
3
4
5
6
7
8
9
10
11
[root@node03 ~]# tail /etc/redis-sentinel.conf 
logfile "/var/log/redis/sentinel.log"
# Generated by CONFIG REWRITE
supervised systemd
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel known-slave mymaster 192.168.34.104 6379
sentinel known-slave mymaster 192.168.34.102 6379
sentinel known-sentinel mymaster 192.168.34.103 26379 1459e120039f6886974a2a8953fbeb362bd1d90a
sentinel known-sentinel mymaster 192.168.34.102 26379 fda45e97ef724fb28d9e398c6a94e3a136cd0d0c
sentinel current-epoch 0

此时将主节点down掉观察效果,会发现,在经过设定的等待时长,且超过半数的sentinel都连接不到主节点时,会自动提升一个从节点为主节点,并将主节点自动降级为从节点。

redis cluster

在哨兵sentinel机制中,可以解决redis高可用的问题,即当master故障后可以自动将slave提升为master从而可以保证redis服务的正常使用,但是无法解决redis单机写入的瓶颈问题,即单机的redis写入性能受限于单机的内存大小、并发数量、网卡速率等因素,因此redis官方在redis 3.0版本之后推出了无中心架构的redis cluster机制,在无中心的redis集群汇中,其每个节点保存当前节点数据和整个集群状态,每个节点都和其他所有节点连接,特点如下:

1:所有Redis节点使用(PING-PING机制)互联
2:集群中某个节点的实效是整个集群中超过半数的节点监测都实效才算真正的实效
3:客户端不需要proxy即可直接连接redis,且客户端不需要连接集群中的所有节点,只要连接集群中的任何一个节点即可。
4:redis cluster把所有的redisnode映射到 0-16383个槽位(slot)上,读写需要到指定的redis node上进行操作,因此有多少个reids node相当于redis 并发扩展了多少倍。
5:Redis集群预先分配16384个(slot)槽位,当需要在redis集群中写入一个key -value的时候,会使用CRC16(key) mod 16384之后的值,决定将key写入值哪一个槽位从而决定写入哪一个Redis节点上,从而有效解决单机瓶颈。

创建redis cluster 集群的前提

1.每个redis node节点采用相同的硬件配置、相同的密码
2.每个节点必须开启参数
cluster-enabled yes #必须开启集群状态,开启后redis 进程会有cluster显示
cluster-config-file nodes-6380.conf #此文件有redis cluster集群自动创建和维护,不需要任何手动操作

创建集群:

1
[root@node01 etc]# redis-cli -a msq --cluster create 192.168.34.101:6379 192.168.34.101:6380 192.168.34.102:6379 192.168.34.102:6380 192.168.34.103:6379 192.168.34.103:6380 --cluster-replicas 1

redis cluster 集群维护

动态添加节点

将节点加入集群

1
[root@node01 redis]# redis-cli -a msq --cluster add-node 192.168.34.104:6379 192.168.34.101:6379

重新分片

1
[root@node01 ~]# redis-cli -a msq --cluster reshard 192.168.34.104:6379

为新加入的master添加一个slave

1
2
[root@node01 ~]# redis-cli -a msq --cluster add-node 192.168.34.104:6380 192.168.34.101:6379
192.168.34.104:6380> CLUSTER REPLICATE c411fffa2a7aac7236fc49f044c018cb474fac78 #后面是刚刚添加的节点的node id,可以在redis-cli炼乳后使用cluster nodes命令获得。

动态删除节点

先将节点的槽位导出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[root@redis-s1 ~]# redis-cli -a 123456  --cluster reshard  192.168.7.102:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing Cluster Check (using node 192.168.7.102:6379)
M: 116c4c6de036fdbac5aaad25eb1a61ea262b64af 192.168.7.102:6379
slots:[6827-10922] (4096 slots) master
1 additional replica(s)
M: 70de3821dde4701c647bd6c23b9dd3c5c9f24a62 192.168.7.103:6379
slots:[12288-16383] (4096 slots) master
1 additional replica(s)
M: 886338acd50c3015be68a760502b239f4509881c 192.168.7.104:6379
slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
1 additional replica(s)
S: 7eda0bcf0c01bb7343313b81267c42dd1b26c8a6 192.168.7.103:6380
slots: (0 slots) slave
replicates 116c4c6de036fdbac5aaad25eb1a61ea262b64af
S: b9a00d59fa3c2a322080a1c7d84f53a2c853b089 192.168.7.104:6380
slots: (0 slots) slave
replicates 886338acd50c3015be68a760502b239f4509881c
S: 7186c6d03dd9a5e3be658f2d08e800bc55b04a09 192.168.7.102:6380
slots: (0 slots) slave
replicates f4cfc5cf821c0d855016488d6fbfb62c03a14fda
S: 2b6e5d9c3944d79a5b64a19e54e52f83d48438d6 192.168.7.101:6380
slots: (0 slots) slave
replicates 70de3821dde4701c647bd6c23b9dd3c5c9f24a62
M: f4cfc5cf821c0d855016488d6fbfb62c03a14fda 192.168.7.101:6379
slots:[1365-5460] (4096 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 4096 #迁移master上的多少个槽位
What is the receiving node ID? 886338acd50c3015be68a760502b239f4509881c #接收槽位的服务器ID
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1: f4cfc5cf821c0d855016488d6fbfb62c03a14fda #从哪个服务器迁移4096个槽位
Source node #2: done #写done,表示没有其他master了
Moving slot 5457 from f4cfc5cf821c0d855016488d6fbfb62c03a14fda
Moving slot 5458 from f4cfc5cf821c0d855016488d6fbfb62c03a14fda
Moving slot 5459 from f4cfc5cf821c0d855016488d6fbfb62c03a14fda
Moving slot 5460 from f4cfc5cf821c0d855016488d6fbfb62c03a14fda
Do you want to proceed with the proposed reshard plan (yes/no)? yes #是否继续

验证槽位迁移完成后然后删除节点
虽然槽位已经迁移完成,但是服务器IP信息还在集群当中,因此还需要将IP信息从集群删除
命令格式: redis-cli -a 123456 –cluster del-node IP:Port ID

1
2
3
4
5
[root@redis-s1 ~]# redis-cli -a 123456 --cluster del-node 192.168.7.101:6379 f4cfc5cf821c0d855016488d6fbfb62c03a14fda
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Removing node f4cfc5cf821c0d855016488d6fbfb62c03a14fda from cluster 192.168.7.101:6379
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.

导入现有redis数据

导入数据之前需要关闭各redis 服务器的密码,包括集群中的各node和源Redis server,避免认证带来的环境不一致从而无法导入,但是可以加参数–cluster-replace 强制替换Redis cluster已有的key。

执行数据导入

将源Redis server的数据直接导入之redis cluster。
命令格式:

  • redis-cli –cluster import 集群服务器IP:PORT –cluster-from 外部Redis node-IP:PORT –cluster-copy –cluster-replace

1
[root@redis-s2 redis]# redis-cli  --cluster import  192.168.7.103:6379 --cluster-from  192.168.7.101:6379  --cluster-copy