Redis入门 (CentOS7 + Redis-3.2.1)

本文详细介绍了在CentOS7系统中安装Redis 3.2.1的步骤,包括编译、测试和安装。接着,文章深入探讨了standalone模式、主从(master-slave)模式的配置与测试。重点在于如何配置和测试Redis集群,包括cluster + master-slave模式,详细解析了集群创建、节点添加、删除、迁移和升级等操作,以及故障转移(fail over)的自动和手动实现。文章旨在为读者提供Redis集群入门知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 编译安装

1.1 下载redis

# cd /tmp/
# wget http://download.redis.io/releases/redis-3.2.1.tar.gz
# tar zxvf redis-3.2.1.tar.gz
# cd redis-3.2.1/

1.2 编译redis

# make

错误:

找不到 <jemalloc/jemalloc.h>

解决:

make distclean

然后重新make;redis的代码包里有自带的jemalloc;


1.3 测试

# yum install tcl

# make test

错误1:

You need tcl 8.5 or newer in order to run the Redis test

解决:

# yum install tcl.x86_64


错误2:

[exception]: Executing test client: NOREPLICAS Not enough good slaves to write..
NOREPLICAS Not enough good slaves to write.

......

Killing still running Redis server 63439
Killing still running Redis server 63486
Killing still running Redis server 63519
Killing still running Redis server 63546
Killing still running Redis server 63574
Killing still running Redis server 63591
I/O error reading reply

......

解决:

vim tests/integration/replication-2.tcl

- after 1000

+ after 10000


错误3:

[err]: Slave should be able to synchronize with the master in tests/integration/replication-psync.tcl
Replication not started.

解决:

遇见过一次,重试make test就ok了。


错误4:

[err]: Test replication partial resync: ok psync (diskless: yes, reconnect: 1) in tests/integration/replication-psync.tcl

解决:

vim tests/integration/replication-psync.tcl

- after 100

+ after 1000


1.4 安装redis

# make install
# cp redis.conf /usr/local/etc/
# cp src/redis-trib.rb /usr/local/bin/

2. standalone模式

2.1 配置redis

# vim etc/redis.conf    
daemonize yes
logfile "/var/run/redis/log/redis.log"
pidfile /var/run/redis/pid/redis_6379.pid
dbfilename redis.rdb
dir /var/run/redis/rdb/

2.2 启动redis

# mkdir -p /var/run/redis/log
# mkdir -p /var/run/redis/rdb
# mkdir -p /var/run/redis/pid
# /usr/local/bin/redis-server /usr/local/etc/redis.conf
# ps -ef | grep redis
root      71021      1  0 15:46 ?        00:00:00 /usr/local/bin/redis-server 127.0.0.1:6379

2.3 测试redis

# /usr/local/bin/redis-cli
127.0.0.1:6379> set country china
OK
127.0.0.1:6379> get country
"china"
127.0.0.1:6379> set country america
OK
127.0.0.1:6379> get country
"america"
127.0.0.1:6379> exists country
(integer) 1
127.0.0.1:6379> del country
(integer) 1
127.0.0.1:6379> exists country
(integer) 0
127.0.0.1:6379>exit

2.4 停止redis

# /usr/local/bin/redis-cli shutdown  

3. master-slave模式

3.1 配置redis

为了测试master-slave模式,我需要在一个host上启动2个redis实例(有条件的话,当然可以使用多个host,每个host运行一个redis实例)。为此,需要把redis.conf复制多份:

# cp /usr/local/etc/redis.conf /usr/local/etc/redis_6379.conf
# cp /usr/local/etc/redis.conf /usr/local/etc/redis_6389.conf

配置实例6379:

<pre name="code" class="plain"># vim /usr/local/etc/redis_6379.conf
daemonize yes
port 6379
logfile "/var/run/redis/log/redis_6379.log"
pidfile /var/run/redis/pid/redis_6379.pid
dbfilename redis_6379.rdb
dir /var/run/redis/rdb/
min-slaves-to-write 1
min-slaves-max-lag 10
 

最后两项配置表示: 在10秒内,至少1个slave ping过master;

配置实例6389:

<pre name="code" class="plain"># vim /usr/local/etc/redis_6389.conf
daemonize yes
port 6389
slaveof 127.0.0.1 6379
logfile "/var/run/redis/log/redis_6389.log"
pidfile /var/run/redis/pid/redis_6389.pid
dbfilename redis_6389.rdb
dir /var/run/redis/rdb/
repl-ping-slave-period 10
 

易见,我将要启动两个redis实例,一个使用端口6379(默认端口),另一个使用6389;并且,前者为master,后者为slave。

repl-ping-slave-period表示slave向master发送PING的频率,单位是秒。

另外,在6389的配置文件中,有如下配置可以修改(一般不需修改):

slave-read-only yes 
slave-serve-stale-data yes

第一个表示:slave是只读的;

第二个表示:当slave在同步新数据(从master同步数据)的时候,它使用旧的数据服务client。这使得slave是非阻塞的。


在6379的配置文件中,有如下配置可以修改(一般不需修改):

# repl-backlog-size 1mb
repl-diskless-sync no
repl-diskless-sync-delay 5

对于这几项,故事是这样的: 

1. 对于一直保持着连接的slave,可以通过增量同步来达到主从一致。

2.  断开重连的slave可能通过部分同步来达到一致(redis 2.8之后才有这一功能,此版本之前,只能和新的slave一样,通过完整同步来达到一致),机制是:

master在内存中记录一些replication积压量;重连的slave与master就replication offset和master run id进行协商:若master run id没变(即master没有重启),并且slave请求的replication offset在积压量里,就可以从offset开始进行部分同步来达到一致。这两个条件任何一个不满足,就必须进行完整同步了。repl-backlog-size 1mb就是用于配置replication积压量大小的。

3.  对于新的slave或者无法通过部分同步达到一致的重连slave,而必须进行完整同步,即传送一个RDB文件。master有两种方式来传这个RDB文件:

  • disk-backed:在磁盘上生成RDB文件,然后传送给slave;
  • diskless:不在磁盘上生成RDB文件,而是一边生成RDB数据,一边直接写到socket;

repl-diskless-sync用于配置使用哪种策略。对于前者,在磁盘上生成一次RDB文件,可以服务多个slave;而对于后者,一旦传送开始,新来的slave只能排队(等当前slave同步完成)。所以,master在开始传送之前,可能希望推迟一会儿,希望来更多的slave,这样master就可以并行的把生成的数据传送给他们。参数repl-diskless-sync-delay 就是用于配置推迟的时间的,单位秒。

慢磁盘的master,可能需要考虑使用diskless传送。


3.2 启动master

# /usr/local/bin/redis-server /usr/local/etc/redis_6379.conf
# /usr/local/bin/redis-cli
127.0.0.1:6379> set country Japan
(error) NOREPLICAS Not enough good slaves to write.
127.0.0.1:6379>

可见,由于slave没启动,不满足在10秒内,至少1个slave ping过master的条件,故出错。


3.3 启动slave

# /usr/local/bin/redis-server /usr/local/etc/redis_6389.conf
# /usr/local/bin/redis-cli
127.0.0.1:6379> set country Japan
OK

3.4 停止redis

# /usr/local/bin/redis-cli -p 6389 shutdown
# /usr/local/bin/redis-cli -p 6379 shutdown


4. cluster + master-slave模式

Cluster能做什么:
  • 自动的将数据集分布到不同节点上;
  • 当一部分节点故障时,能够继续服务;
数据分布:redis不使用一致性hash,而是另一种形式的sharding:一共用16384个hash slot,它们分布在不同的节点上(例如节点A包含0-4999,节点B包含5000-9999,节点C包含10000-16384)。key被映射到hash slot上。比如,key_foo被映射到slot 1000,而slot 1000存储于节点A上,那么key_foo(以及它的值)将存储于节点A上。另外,你可以让不同的key映射到同一个slot上,方法是使用{}把key的一部分括起来;在key到slot的映射过程中,只考虑{}之内的部分。例如,this{foo}key和another{foo}key在映射中,只有"foo"被考虑,所以它们一定映射到相同的slot。

TCP port:每个节点使用两个端口:服务client的端口;集群bus端口。集群bus端口 = 服务client的端口 + 10000。配置过程中只需指定服务client的端口,后者由redis根据这个规则自行计算。集群bus端口用于故障侦测、配置更新、fail over鉴权等;服务client的端口除了用于服务客户,还用于节点间迁移数据。 服务client的端口必须对client和所有其他节点开放;集群bus端口必须对所有其他节点开放。

一致性保证:redis集群不能保证强一致性。也就是说, 在特定情况下,redis可能丢失写入的数据(虽然已经回应client:已成功写入)。
  • 异步复制导致数据丢失:1. 用户写入master节点B;2. master节点B向client回复OK;3. master节点B把写入数据复制到它的slave。可见,因为B不等slave确认写入就向client回复OK,若master节点B在2之后故障,就会导致数据丢失。
  • 网络分裂导致数据丢失:例如有A,B,C三个master,它们的slave分别是A1,B1,C1;如果发生网络分裂,B和客户端分到一侧。在cluster-node-timeout之内,客户端可以继续向B写入数据;当超过cluster-node-timeout时,分裂的另一侧发生fail over,B1当选为master。客户端向B写的数据就丢失了。
  • redis(非cluster模式)本身也可能丢失数据:1. RBD定期快照,导致快照周期内的数据丢失;2. AOF,虽然每一个写操作都记入log,但log是定期sync的,也可能丢失sync周期内的数据。

在下文,节点和实例是可以互换的名词(因为,我是在同一个host上试验集群,一个节点由一个实例代替)。

我将在同一台机器上试验redis集群模式,为此,我需要创建6个redis实例,其中3个master,另外3个是slave。它们的端口是7000-7005。

4.1 配置redis集群:

<pre name="code" class="plain"># cp /usr/local/etc/redis.conf  /usr/local/etc/redis_7000.conf
# vim /usr/local/etc/redis_7000.conf
daemonize yes
port 7000
pidfile /var/run/redis/pid/redis_7000.pid
logfile "/var/run/redis/log/redis_7000.log"
dbfilename redis_7000.rdb
dir /var/run/redis/rdb/
min-slaves-to-write 0
cluster-enabled yes
cluster-config-file /var/run/redis/nodes/nodes-7000.conf
cluster-node-timeout 5000
cluster-slave-validity-factor 10
repl-ping-slave-period 10
 

这里我把min-slave-to-write改为0,为了后文验证fail over之后,仍能够读写(否则,master crash之后,slave取代它成为master,但它没有slave,故不能读写)。

# cp /usr/local/etc/redis_7000.conf /usr/local/etc/redis_7001.conf
# cp /usr/local/etc/redis_7000.conf /usr/local/etc/redis_7002.conf
# cp /usr/local/etc/redis_7000.conf /usr/local/etc/redis_7003.conf
# cp /usr/local/etc/redis_7000.conf /usr/local/etc/redis_7004.conf
# cp /usr/local/etc/redis_7000.conf /usr/local/etc/redis_7005.conf
# sed -i -e 's/7000/7001/' /usr/local/etc/redi
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值