一 . Redis 是什么
Redis 是完全开源免费的,遵守 BSD 协议,是一个高性能的 key - value 数据库
Redis 与 其他 key - value 缓存产品有以下三个特点:
-
Redis 支持数据持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
-
Redis 不仅仅支持简单的 key - value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储
-
Redis 支持数据的备份,即 master - slave 模式的数据备份
二 . Redis 优势
-
性能极高 – Redis 读的速度是 110000 次 /s, 写的速度是 81000 次 /s 。
-
丰富的数据类型 - Redis 支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
-
原子性 - Redis 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTI 和 EXEC 指令包起来。
-
其他特性 - Redis 还支持 publish/subscribe 通知,key 过期等特性。
三 . Redis 数据类型
Redis 支持 5 中数据类型:
string(字符串),hash(哈希),list(列表),set(集合),zset(sorted set:有序集合)
string
string 是 redis 最基本的数据类型。一个 key 对应一个 value。
string 是二进制安全的。也就是说 redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象。
string 类型是 redis 最基本的数据类型,string 类型的值最大能存储 512 MB。
理解:string 就像是 java 中的 map 一样,一个 key 对应一个 value
![](https://i-blog.csdnimg.cn/blog_migrate/e193a78bddacbc7032698c353f29936e.png)
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"
hash
Redis hash 是一个 string 类型的 key 和 value 的映射表,hash 特别适合用于存储对象。
理解:可以将 hash 看成一个 key - value 的集合。也可以将其想成一个 hash 对应着多个 string。
与 string 区别:string 是 一个 key - value 键值对,而 hash 是多个 key - value 键值对。
![](https://i-blog.csdnimg.cn/blog_migrate/0bf0c070d68bf880d374186403c00b0f.png)
// hash-key 可以看成是一个键值对集合的名字,在这里分别为其添加了 sub-key1 : value1、
sub-key2 : value2、sub-key3 : value3 这三个键值对
127.0.0.1:6379> hset hash-key sub-key1 value1
(integer) 1
127.0.0.1:6379> hset hash-key sub-key2 value2
(integer) 1
127.0.0.1:6379> hset hash-key sub-key3 value3
(integer) 1
// 获取 hash-key 这个 hash 里面的所有键值对
127.0.0.1:6379> hgetall hash-key
1) "sub-key1"
2) "value1"
3) "sub-key2"
4) "value2"
5) "sub-key3"
6) "value3"
// 删除 hash-key 这个 hash 里面的 sub-key2 键值对
127.0.0.1:6379> hdel hash-key sub-key2
(integer) 1
127.0.0.1:6379> hget hash-key sub-key2
(nil)
127.0.0.1:6379> hget hash-key sub-key1
"value1"
127.0.0.1:6379> hgetall hash-key
1) "sub-key1"
2) "value1"
3) "sub-key3"
4) "value3"
list
Redis 列表是简单的字符串列表,按照插入顺序排序。我们可以网列表的左边或者右边添加元素。
![](https://i-blog.csdnimg.cn/blog_migrate/1d6a449d19d7d0a124dec7ceb036cf9c.png)
127.0.0.1:6379> rpush list-key v1
(integer) 1
127.0.0.1:6379> rpush list-key v2
(integer) 2
127.0.0.1:6379> rpush list-key v1
(integer) 3
127.0.0.1:6379> lrange list-key 0 -1
1) "v1"
2) "v2"
3) "v1"
127.0.0.1:6379> lindex list-key 1
"v2"
127.0.0.1:6379> lpop list
(nil)
127.0.0.1:6379> lpop list-key
"v1"
127.0.0.1:6379> lrange list-key 0 -1
1) "v2"
2) "v1"
set
redis 的 set 是字符串类型的无序集合。集合是通过哈希表实现的,因此添加、删除、查找的复杂度都是 O(1)
![](https://i-blog.csdnimg.cn/blog_migrate/a913cc5612d869cbfcd94df4662beaa4.png)
127.0.0.1:6379> sadd k1 v1
(integer) 1
127.0.0.1:6379> sadd k1 v2
(integer) 1
127.0.0.1:6379> sadd k1 v3
(integer) 1
127.0.0.1:6379> sadd k1 v1
(integer) 0
127.0.0.1:6379> smembers k1
1) "v3"
2) "v2"
3) "v1"
127.0.0.1:6379>
127.0.0.1:6379> sismember k1 k4
(integer) 0
127.0.0.1:6379> sismember k1 v1
(integer) 1
127.0.0.1:6379> srem k1 v2
(integer) 1
127.0.0.1:6379> srem k1 v2
(integer) 0
127.0.0.1:6379> smembers k1
1) "v3"
2) "v1"
redis 的 set 与 java 中的 set 还是有点区别的。
但是和 redis 的 list 不同的是 set 中的字符串集合元素不能重复,但是 list 可以。
Zset
redis zset 和 set 一样都是 字符串类型元素的集合,并且集合内的元素不能重复。
不同的是,zset 每个元素都会关联一个 double 类型的分数。redis 通过分数来为集合中的成员进行从小到大的排序。
zset 的元素是唯一的,但是分数(score)却可以重复。
![](https://i-blog.csdnimg.cn/blog_migrate/eb076d18f3f2f91b5c828d5a3318b979.png)
127.0.0.1:6379> zadd zset-key 728 member1
(integer) 1
127.0.0.1:6379> zadd zset-key 982 member0
(integer) 1
127.0.0.1:6379> zadd zset-key 982 member0
(integer) 0
127.0.0.1:6379> zrange zset-key 0 -1 withscores
1) "member1"
2) "728"
3) "member0"
4) "982"
127.0.0.1:6379> zrangebyscore zset-key 0 800 withscores
1) "member1"
2) "728"
127.0.0.1:6379> zrem zset-key member1
(integer) 1
127.0.0.1:6379> zrem zset-key member1
(integer) 0
127.0.0.1:6379> zrange zset-key 0 -1 withscores
1) "member0"
2) "982"
![](https://i-blog.csdnimg.cn/blog_migrate/976022418d5dbad7fb9706bdedf88681.png)
5.1 导入依赖与配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring:
redis:
#host: 127.0.0.1 #单实例在此配置ip,配置单实例必须屏蔽cluster max-redirects 与 nodes
#port: 6379 #单实例在此配置端口
password:
timeout: 20000
pool:
max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
min-idle: 0 #最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接
max-idle: 8 #最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
sentinel: #哨兵模式 适用于读多写少
master: #配置主节点
nodes: #配置从节点
cluster: #集群在此配置节点,配置集群必须屏蔽host与port配置
max-redirects: 6 #最大的要重定向的次数(由于集群中数据存储在多个节点所以,在访问数据时需要通过节点进行转发)
nodes: 192.168.210.68:6379,192.168.210.68:6380,192.168.210.68:6381,... #分片至少要6个节点才能使用
![](https://i-blog.csdnimg.cn/blog_migrate/752404e429510dcf4061a6b3970bc4a5.png)
存在的问题:无法动态增加减少服务节点。
5.4 分片式集群的使用
/**
* 集群式的连接池
*/
public class ShardedJedisPoolDemo {
public static void main(String[] args) {
// 构建连接池配置信息
JedisPoolConfig poolConfig = new JedisPoolConfig();
// 设置最大连接数
poolConfig.setMaxTotal(50);
// 定义集群信息
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo("127.0.0.1", 6379));
//shards.add(new JedisShardInfo("192.168.48.22", 6379));
// 定义集群连接池
ShardedJedisPool shardedJedisPool = new ShardedJedisPool(poolConfig, shards);
ShardedJedis shardedJedis = null;
try {
// 从连接池中获取到jedis分片对象
shardedJedis = shardedJedisPool.getResource();
// 从redis中获取数据
String value = shardedJedis.get("name");
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != shardedJedis) {
// 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态
shardedJedis.close();
}
}
// 关闭连接池
shardedJedisPool.close();
}
}
六. redis如何实现高可用
保证redis高可用机制需要redis主从复制、redis持久化机制、哨兵机制、keepalived等的支持。
6.1 redis主从复制原理
1、redis的复制功能是支持多个数据库之间的数据同步。一类是主数据库(master)一类是从数据库(slave),主数据库可以进行读写操作,当发生写操作的时候自动将数据同步到从数据库,而从数据库一般是只读的,并接收主数据库同步过来的数据,一个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库。
2、通过redis的复制功能可以很好的实现数据库的读写分离,提高服务器的负载能力。主数据库主要进行写操作,而从数据库负责读操作。
主从复制全量同步的过程:见下图
Redis主从复制可以根据是否是全量分为全量同步和增量同步
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。
全量同步过程:
1:当一个从数据库启动时,会向主数据库发送sync命令,
2:主数据库接收到sync命令后会开始在后台保存快照(执行rdb操作),并用缓存区记录后续的所有写操作
3:当主服务器快照保存完成后,redis会将快照文件发送给从数据库。
4:从数据库收到快照文件后,会丢弃所有旧数据,载入收到的快照。
5: 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令。
6: 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令。
增量同步的过程:
Redis增量复制是指slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。
增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。
主从服务器刚刚连接的时候,会先进行全量同步;全同步结束后,再进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
redis主从复制如何配置呢?
修改从服务器redis/conf中的redis.conf文件
修改IP地址和端口号为主服务器的IP和端口
slaveof 10.211.55.9 6379
masterauth 123456--- 如果主redis服务器配置了密码,则需要配置
6.2 Redis哨兵机制
哨兵机制需要主从复制的支持。
Redis的哨兵(sentinel) 系统用于管理多个 Redis 服务器,该系统执行以下三个任务:
· 监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常。
· 提醒(Notification):当被监控的某个Redis出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。
· 自动故障迁移(Automatic failover):当一个Master不能正常工作时,哨兵(sentinel) 会开始一次自动故障迁移操作,它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其他Slave改为复制新的Master; 当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用Master代替失效Master。
哨兵(sentinel) 是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossipprotocols)来接收关于Master是否下线的信息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master.
每个哨兵(sentinel) 会向其它哨兵(sentinel)、master、slave定时发送消息,以确认对方是否”活”着,如果发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓的”主观认为宕机” Subjective Down,简称sdown).
若“哨兵群”中的多数sentinel,都报告某一master没响应,系统才认为该master"彻底死亡"(即:客观上的真正down机,Objective Down,简称odown),通过一定的vote算法,从剩下的slave节点中,选一台提升为master,然后自动修改相关配置.
虽然哨兵(sentinel) 释出为一个单独的可执行文件 redis-sentinel ,但实际上它只是一个运行在特殊模式下的 Redis 服务器,你可以在启动一个普通 Redis 服务器时通过给定 --sentinel 选项来启动哨兵(sentinel).
哨兵(sentinel) 的一些设计思路和zookeeper非常类似
单个哨兵(sentinel)
6.2 Redis哨兵机制
哨兵机制需要主从复制的支持。
Redis的哨兵(sentinel) 系统用于管理多个 Redis 服务器,该系统执行以下三个任务:
· 监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常。
· 提醒(Notification):当被监控的某个Redis出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。
· 自动故障迁移(Automatic failover):当一个Master不能正常工作时,哨兵(sentinel) 会开始一次自动故障迁移操作,它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其他Slave改为复制新的Master; 当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用Master代替失效Master。
哨兵(sentinel) 是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossipprotocols)来接收关于Master是否下线的信息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master.
每个哨兵(sentinel) 会向其它哨兵(sentinel)、master、slave定时发送消息,以确认对方是否”活”着,如果发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓的”主观认为宕机” Subjective Down,简称sdown).
若“哨兵群”中的多数sentinel,都报告某一master没响应,系统才认为该master"彻底死亡"(即:客观上的真正down机,Objective Down,简称odown),通过一定的vote算法,从剩下的slave节点中,选一台提升为master,然后自动修改相关配置.
虽然哨兵(sentinel) 释出为一个单独的可执行文件 redis-sentinel ,但实际上它只是一个运行在特殊模式下的 Redis 服务器,你可以在启动一个普通 Redis 服务器时通过给定 --sentinel 选项来启动哨兵(sentinel).
哨兵(sentinel) 的一些设计思路和zookeeper非常类似
单个哨兵(sentinel)
哨兵模式如何配置?
注意:哨兵机制是redis自带的功能,不需要接入第三方实现
实现步骤: 哨兵机制端口号默认为26379
1.修改sentinel.conf配置文件(该文件存在于redis安装包根目录下)
注意:初次配置,不需要打开#sentinel monitor mymaster注释,因为后几行有默认当台服务器为主服务器
原配置:sentinel monitor mymaster 127.0.0.1 6379 2 通过这句来修改为:
sentinel monitor mymaster 10.211.55.3 6379 1 #主服务器名称 IP 端口号 选举次数(redis集群服务器不多时可以配置成1)
2.修改下一行:sentinel auth-pass mymaster 123456 # 第一个参数mymaster为主节点名称,123456为主服务器密码。
3. 修改心跳检测 5000毫秒【默认为30秒】
sentinel down-after-milliseconds mymaster 5000
4.sentinel parallel-syncs mymaster 2 --- 指定了在执行故障转移时,最多可以有多少个从Redis实例在同步新的主实例,在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长
5. 启动哨兵模式【cd到redis安装根目录下启动,因为需要运行redis-server】
./redis-server sentinel.conf --sentinel &
启动后如果打印+ monitor master 主节点名 ip 和 +slave slave ip则表示启动成功
6.可以通过模拟——主服务器进入redis-cli,输入shutdown,观察哨兵所在服务器日志打印。原从服务器本不能写操作,后由于哨兵自动故障迁移把某一个slave服务器升级为master服务器,则该升级后的服务器又可以进行写操作。
![](https://i-blog.csdnimg.cn/blog_migrate/473b5bf5fe4a87e59fad5262db528074.png)
光靠redis主从复制和哨兵机制不足以实现redis高可用。为什么呢?
因为若某一节点宕机后,不会实现自动重启。最稳健实现高可用的做法 :
redis主从复制+哨兵机制(监控、提醒、自动故障迁移)+keepalived(自动重启),若重启多次仍不成功,可以通过邮件短信等方式通知。
七. redis持久化(rdb和aof)
Redis面试知识点
1.Redis 是单进程单线程的,redis 利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销
2.一个字符串类型的值能存储最大容量是512M
3.redis的数据类型,以及每种数据类型的使用场景
(一)String这个其实没啥好说的,最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计数功能的缓存。
(二)hash这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。博主在做单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。
(三)list使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。
(四)set因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。
(五)sorted set
sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。另外,参照另一篇《分布式之延时任务方案解析》,该文指出了sorted set可以用来做延时任务。最后一个应用就是可以做范围查找。
4.redis 过期键的删除策略
(1)定时删除:在设置键的过期时间的同时,创建一个定时器 timer). 让定时器在键的过期时间来临时,立即执行对键的删除操作。
(2)惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。
(3)定期删除:每隔一段时间程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。
5. redis和数据库双写一致性问题
分析:一致性问题是分布式常见问题,还可以再分为最终一致性和强一致性。数据库和缓存双写,就必然会存在不一致的问题。答这个问题,先明白一个前提。就是如果对数据有强一致性要求,不能放缓存。我们所做的一切,只能保证最终一致性。另外,我们所做的方案其实从根本上来说,只能说降低不一致发生的概率,无法完全避免。因此,有强一致性要求的数据,不能放缓存。回答:首先,采取正确更新策略,先更新数据库,再删缓存。其次,因为可能存在删除缓存失败的问题,提供一个补偿措施即可,例如利用消息队列。
6 .如何应对缓存穿透和缓存雪崩问题
缓存穿透:即黑客故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。
解决方案:(一)利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试(二)采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。(三)提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。
缓存雪崩,即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。
解决方案:(一)给缓存的失效时间,加上一个随机值,避免集体失效。(二)使用互斥锁,但是该方案吞吐量明显下降了。(三)双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时间。自己做缓存预热操作。然后细分以下几个小点
I 从缓存A读数据库,有则直接返回
II A没有数据,直接从B读数据,直接返回,并且异步启动一个更新线程。
III 更新线程同时更新缓存A和缓存B。
7. 如何解决redis的并发竞争key问题
分析:这个问题大致就是,同时有多个子系统去set一个key。这个时候要注意什么呢?大家思考过么。需要说明一下,我提前百度了一下,发现答案基本都是推荐用redis事务机制。但是我并不推荐使用redis的事务机制。因为我们的生产环境,基本都是redis集群环境,做了数据分片操作。你一个事务中有涉及到多个key操作的时候,这多个key不一定都存储在同一个redis-server上。因此,redis的事务机制,十分鸡肋。
回答:如下所示(1)如果对这个key操作,不要求顺序这种情况下,准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可,比较简单。(2)如果对这个key操作,要求顺序假设有一个key1,系统A需要将key1设置为valueA,系统B需要将key1设置为valueB,系统C需要将key1设置为valueC.期望按照key1的value值按照 valueA-->valueB-->valueC的顺序变化。这种时候我们在数据写入数据库的时候,需要保存一个时间戳。假设时间戳如下
系统A key 1 {valueA 3:00}
系统B key 1 {valueB 3:05}
系统C key 1 {valueC 3:10}
那么,假设这会系统B先抢到锁,将key1设置为{valueB 3:05}。接下来系统A抢到锁,发现自己的valueA的时间戳早于缓存中的时间戳,那就不做set操作了。以此类推。
其他方法,比如利用队列,将set方法变成串行访问也可以。总之,灵活变通。
8.redis内存淘汰机制
第四点我们一般采用定期删除+惰性删除。但是这种策略还是会有一些问题,如果定期删除没删除key。然后你也没即时去请求key,也就是说惰性删除也没生效。这样,redis的内存会越来越高。那么就应该采用内存淘汰机制。在redis.conf中有一行配置
# maxmemory-policy allkeys-lru
该配置就是配内存淘汰策略的(什么,你没配过?好好反省一下自己)1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。应该没人用吧。2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。推荐使用。3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。应该也没人用吧,你不删最少使用Key,去随机删。4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。这种情况一般是把redis既当缓存,又做持久化存储的时候才用。不推荐5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。依然不推荐6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。不推荐ps:如果没有设置 expire 的key, 不满足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致。
redis 的 set 与 java 中的 set 还是有点区别的。
但是和 redis 的 list 不同的是 set 中的字符串集合元素不能重复,但是 list 可以。
Zset
redis zset 和 set 一样都是 字符串类型元素的集合,并且集合内的元素不能重复。
不同的是,zset 每个元素都会关联一个 double 类型的分数。redis 通过分数来为集合中的成员进行从小到大的排序。
zset 的元素是唯一的,但是分数(score)却可以重复。
1.修改sentinel.conf配置文件(该文件存在于redis安装包根目录下)
注意:初次配置,不需要打开#sentinel monitor mymaster注释,因为后几行有默认当台服务器为主服务器
原配置:sentinel monitor mymaster 127.0.0.1 6379 2 通过这句来修改为:
sentinel monitor mymaster 10.211.55.3 6379 1 #主服务器名称 IP 端口号 选举次数(redis集群服务器不多时可以配置成1)
2.修改下一行:sentinel auth-pass mymaster 123456 # 第一个参数mymaster为主节点名称,123456为主服务器密码。
3. 修改心跳检测 5000毫秒【默认为30秒】
sentinel down-after-milliseconds mymaster 5000
4.sentinel parallel-syncs mymaster 2 --- 指定了在执行故障转移时,最多可以有多少个从Redis实例在同步新的主实例,在从Redis实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长
5. 启动哨兵模式【cd到redis安装根目录下启动,因为需要运行redis-server】
./redis-server sentinel.conf --sentinel &
启动后如果打印+ monitor master 主节点名 ip 和 +slave slave ip则表示启动成功
6.可以通过模拟——主服务器进入redis-cli,输入shutdown,观察哨兵所在服务器日志打印。原从服务器本不能写操作,后由于哨兵自动故障迁移把某一个slave服务器升级为master服务器,则该升级后的服务器又可以进行写操作。
光靠redis主从复制和哨兵机制不足以实现redis高可用。为什么呢?
因为若某一节点宕机后,不会实现自动重启。最稳健实现高可用的做法 :
redis主从复制+哨兵机制(监控、提醒、自动故障迁移)+keepalived(自动重启),若重启多次仍不成功,可以通过邮件短信等方式通知。