目录
redis单点、redis主从、redis哨兵 sentinel,redis集群cluster配置搭建与使用
redis是如今被互联网公司使用最广泛的一个中间件,我们打开GitHub搜索redis,边可以看到,该项目的介绍是这样的:
Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes, HyperLogLogs, Bitmaps.
从这句话中,我们可以提取其特性的关键字:
in-memory database ,内存数据库
support:Strings , lists, sets ,hashes ,hyperloglogs, bitmaps
也就是高性能,支持数据类型多。本文假设你已经了解redis的基本使用,进而讨论redis的单点,高可用,集群。
redis的安装十分简单,打开redis的官网 redis.io 。
下载一个最新版本的安装包,如 redis-version.tar.gz
解压 tar zxvf redis-version.tar.gz
执行 make (执行此命令可能会报错,例如确实gcc,一个个解决即可)
如果是 mac 电脑,安装redis将十分简单执行brew install redis即可。
安装好redis之后,我们先不慌使用,先进行一些配置。打开redis.conf文件,我们主要关注以下配置:
安装好redis之后,我们来运行一下。启动redis的命令为 :
redishome/bin/redis-server path/to/redis.config
假设我们没有配置后台运行(即:daemonize no),那么我们会看到如下启动日志:
无论是否配置了后台运行,启动成功之后,我们可以新开一个命令行窗口来操作试试。
使用命令:telnet localhost 6379 来连接redis,或者你可以直接使用代码来连接测试。连接之后,看到如下信息:
我们输入几个命令试试:
如此,我们便体验了一把redis,可以说是非常简单了。刚才我们是使用命令行来操作redis的,下面我们来使用代码操作一下redis,以Java为例,我们使用一个开源的 java - redis客户端。
打开GitHub,搜索redis,进入到项目主页之后,我们可以看到使用方法:
加入jedis依赖
redis.clients
jedis
3.0.0
jar
compile
编写代码如下
Jedis jedis = new Jedis("localhost",6379);
jedis.set("hello", "world");
String value = jedis.get("hello");
System.out.println(value); // get world
jedis.del("hello");
System.out.println(jedis.get("hello"));// get null
上面jedis操作redis的例子很简单,除了使用jedis之外,还可以使用spring-redis。步骤如下
配置redis
编写代码
public class Example {
}
Lettuce是一个基于netty的 非阻塞的 redis客户端。支持Java8以及响应式。其官网为 lettuce.io/。Lettuce也可以和spring搭配使用。
使用Lettuce需要加入如下maven依赖:
基本的 get,set示例代码如下:
上面我们启动了一台redis,并对其进行操作。当然这只是实验性的玩玩。假设我们生产环境使用了一台redis,redis挂了怎么办?如果等到运维重启redis,并恢复好数据,可能需要花费很长时间。那么在这期间,我们的服务是不可用的,这应该是不能容忍的。假设我们做了主从,主库挂了之后,运维让从库接管,那么服务可以继续运行,正所谓有备无患。
redis主从配置非常简单,过程如下(ps 演示情况下主从配置在一台电脑上):
复制两个redis配置文件(启动两个redis,只需要一份redis程序,两个不同的redis配置文件即可)
mkdir redis-master-slave
cp path/to/redis/conf/redis.conf path/to/redis-master-slave master.conf
cp path/to/redis/conf/redis.conf path/to/redis-master-slave slave.conf
修改配置
port 6379
port 6380
slaveof 127.0.0.1 6379
分别启动两个redis
redis-server path/to/redis-master-slave/master.conf
redis-server path/to/redis-master-slave/slave.conf
启动之后,打开两个命令行窗口,分别执行telnet localhost 6379 telnet localhost 6380
然后分别在两个窗口中执行 info 命令,可以看到
主从配置没问题。
然后在master 窗口执行 set 之后,到slave窗口执行get,可以get到,说明主从同步成功。
这时,我们如果在slave窗口执行 set ,会报错:
因为从节点是只读的。
上面我们介绍了主从,从库作为一个“傀儡”,可以在需要的时候“顶上来”,”接盘“。我们配置的主从是为了”有备无患“,在主redis挂了之后,可以立马切换到从redis上,可能只需要花几分钟的时间,但是仍然是需要人为操作。假设主redis在晚上23点挂了,10分钟之后你接到电话,老板让你赶紧修复,于是你从被窝爬起来整,岂不是很头疼。假如你关机了,又其他人知道服务器密码,那系统岂不是要停机一晚上?太可怕了。
这个时候redis sentinel 就派上用场了。sentinel 通常翻译成哨兵,就是放哨的,这里它就是用来监控主从节点的健康情况。客户端连接redis主从的时候,先连接 sentinel,sentinel会告诉客户端主redis的地址是多少,然后客户端连接上redis并进行后续的操作。当主节点挂掉的时候,客户端就得不到连接了因而报错了,客户端重新想sentinel询问主master的地址,然后客户端得到了[新选举出来的主redis],然后又可以愉快的操作了。
为了说明sentinel的用处,我们做个试验。配置3个redis(1主2从),1个哨兵。步骤如下:
上我们创建了 3个redis配置文件,1个哨兵配置文件。我们将 redis01设置为master,将redis02,redis03设置为slave。
上面的主从配置都熟悉,只有哨兵配置 sentinel.conf,需要解释一下:
上面我们配置好了redis主从,1主2从,以及1个哨兵。下面我们分别启动redis,并启动哨兵
启动之后,可以分别连接到 3个redis上,执行info查看主从信息。
下面使用程序来连接哨兵,并操作redis。
程序非常简单,循环运行20次,连接哨兵,将随机字符串 set到redis,get结果。打印信息,异常捕获。
运行上面的程序(注意,在实验这个效果的时候,可以将sleep时间加长或者for循环增多,以防程序提前停止,不便看整体效果),然后将主redis关掉,模拟redis挂掉的情况。现在主redis为redis01,端口为63791
这个时候如果sentinel没有设置后台运行,可以在命令行窗口看到 master切换的情况日志。
上面的日志较多,仔细找找可以看到下面几行主要的:
这个日志比较晦涩,从代码运行效果看,如下:
从结果看出
开始正常操作redis,并设置了两次。
主redis挂了,jedis得不到连接,报错了JedisConnectionException:Could not get a resource from the pool
主redis没选好之前,程序持续报错。
主redis选好了,程序正常运行,最后结束。
我们看到最后一次运行设置的值是aajhbjagag,我们可以连接剩下的2台redis中的任意一台,get hello,结果肯定是一致的。
上面的章节中,我们分别学习了redis 单点,redis主从,并增加了高可用的 sentinel 哨兵模式。我们所做的这些工作只是保证了数据备份以及高可用,目前为止我们的程序一直都是向1台redis写数据,其他的redis只是备份而已。实际场景中,单个redis节点可能不满足要求,因为:
单个redis并发有限
单个redis接收所有的数据,最终回导致内存太大,内存太大回导致rdb文件过大,从很大的rdb文件中同步恢复数据会很慢。
所有,我们需要redis cluster 即redis集群。
Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。
Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.
Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令. Redis 集群的优势:
自动分割数据到不同的节点上。
整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
为了配置一个redis cluster,我们需要准备至少6台redis,为啥至少6台呢?我们可以在redis的官方文档中找到如下一句话:
因为最小的redis集群,需要至少3个主节点,既然有3个主节点,而一个主节点搭配至少一个从节点,因此至少得6台redis。然而对我来说,就是复制6个redis配置文件。本实验的redis集群搭建依然在一台电脑上模拟。
上面提到,配置redis集群需要至少6个redis节点。因此我们需要准备及配置的节点如下:
上面的配置完成之后,分别启动6个redis实例。配置正确的情况下,都可以启动成功。然后运行如下命令创建集群:
注意,这里使用的是ip:port,而不是 domain:port ,因为我在使用 localhost:6371 之类的写法执行的时候碰到错误:
执行成功之后,连接一台redis,执行 cluster info 会看到类似如下信息:
我们可以看到cluster_state:ok,cluster_slots_ok:16384,cluster_size:3。
上面我们配置了一个redis集群,包含6个redis节点,3主3从。下面我们来使用jedis来连接redis集群。代码如下:
上面我们设置了信息set foo bar,但是不知道被设置到那一台redis上去了。请读者思考一下,我们是集群模式,所以数据被分散放到不同的槽中了,Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:
节点 A 包含 0 到 5500号哈希槽.
节点 B 包含5501 到 11000 号哈希槽.
节点 C 包含11001 到 16384号哈希槽.
看到这里你应该还是不知道set foo bar 放到哪台redis上去了,不妨尝试连接任意一台redis探索一下,你会知道的。
至此,我们了解并动手实践了redis的安装,redis单点,redis主从,redis 哨兵 sentinel,redis 集群cluster。
我们来梳理一下redis主从,redis哨兵,redis机器的区别和关系。
redis主从:是备份关系, 我们操作主库,数据也会同步到从库。 如果主库机器坏了,从库可以上。就好比你 D盘的片丢了,但是你移动硬盘里边备份有。
redis哨兵:哨兵保证的是HA,保证特殊情况故障自动切换,哨兵盯着你的“redis主从集群”,如果主库死了,它会告诉你新的老大是谁。
redis集群:集群保证的是高并发,因为多了一些兄弟帮忙一起扛。同时集群会导致数据的分散,整个redis集群会分成一堆数据槽,即不同的key会放到不不同的槽中。
主从保证了数据备份,哨兵保证了HA 即故障时切换,集群保证了高并发性。
一切动手做了才会熟悉。