笔记来源
bilibili狂神说-redis学习视频
访问官网,点击首页的download it即可下载,Windows要去github上下载,但是已经停更很久了,redis官网不建议使用Windows系统,存在兼容问题。
redis GitHub Windows下载安装包
点击官网这里,在介绍中有说不支持Windows,但是Windows官方在支持redis,可以点击这个Windows支持的版本去GitHub上下载安装包。在GitHub上点击Releases,选择对应版本下载即可。
使用redis客户端连接服务,双击redis-cli.exe,发现黑窗口127.0.0.1:6379,表示已经连接,输入命令ping,响应pang表示连接成功。
下载安装包,访问官网,点击download it即可。中文网和英文网的版本有点区别
使用xftp或其他软件将安装包上传至服务器
移动压缩包到opt目录下
使用命令tar -zxvf redis-5.0.8.tar.gz
解压,解压后如图,这里需要注意的是这个redis.conf这个文件和sentinel.conf,这两个一个是redis-server的配置文件,另一个是哨兵模式的配置文件
安装gcc环境,执行命令yum install gcc-c++
使用命令gcc -v
查看是否安装成功
make
命令加载依赖库,等待一段时间,大概几分钟。完成之后再执行make命令,就会发现很快。完成之后就会发现redis已经安装成功,再执行make install(可以不执行,只是为了确认),就会发现都已经安装成功了。
redis的默认安装路径/usr/local/bin
,安装完成后在该目录下可以查看,文件与Windows是一样的,如图,下图中的redisredis-sentinel就是哨兵,哨兵是一个单独的进程。
将解压后的文件内redis.conf文件拷贝到当前目录下 cp /opt/redis-5.0.8/redis.conf /usr/local/bin
,这样就即保留了原始的配置文件在解压目录中,又可以更改当前目录下的配置文件自定义配置启动redis。
redis默认不是后台启动的,因此需要修改配置
修改配置文件,vim redis.conf,这里需要修改的是usr/local/bin
下的配置文件,
启动redis服务redis-server redis.conf
表示使用该配置文件启动redis服务
查看redis进程是否开启
ps -ef|grep redis
关闭redis服务,shutdown命令表示停止服务,exit表示退出。
redis-benchmark 使用命令与redis-server类似,使用redis-benchmark -h 127.0.0.1 -p 6379 ....
测试结果如下:
.\redis-cli.exe -h 192.168.0.113 -p 6379
win10默认不用当前目录命令,因此前面添加.\。exists key
判断某个key是否存在expire key
设置key过期时间,如果设置10秒,则expire key 10
ttl key
查看key还剩多久过期,如果已经过期,则返回-2move key
移除keytype key
判断当前key是什么类型,string还是list等等小提示:使用redis-cli工具连接服务时,输入的命令会有提示
append key value
在字符串后面追加value,返回数字,如果key不存在,就相当于set keystrlen key
返回key的值的字符串长度incr key
给这个key的值+1。如果这个key不存在,则相当于set key 1.如果这个key的值不是一个数字,则返回 ERR value is not an integer or out of range。value不是一个数字或超出范围,范围是多大我也不知道,应该是integer的取值范围2147483648。decr key
给这个key减一incrby key 10
给这个key设置每次增加10,设置步长,指定增量decrby key 5
给这个key设置每次自减5.getrange key 0 3
获取key对应字符串的部分,相当于java的substring,如果是getranger key 0 -1
则表示获取key的所有=GET KEY,而不是截取的部分setrange key 2 xx
将字符串中下标为2的值替换为xx,例如set key1 abcde
setrange key1 2 xx
get key1
返回abxxcd。相当于java的replacesetex key second value
表示设置后多少秒过期,seconds表示过期时间。ex就是expiresetnx key value
表示如果这个key不存在才设置,如果存在则不设置。nx就是 not existmset k1 v1 k2 v2 k3 v3 ...
表示同时设置多个键值对mget k1 k2 k3
同时获取多个msetnx k1 v1 k2 v2 k3 v3 k4 v4..
如果不存在则设置,如果key有一个存在的,则所有的都设置不成功。这是一个原子性的操作,redis的事务是不保证原子性操作的,但是msetnx是保证原子性操作的。
举例:
当我们要在redis中保存一个用户的信息的时候,一般情况下是将user对象转为json串保存到redis中
mset user:1 {name:zhangsan,age:10...}
,表示设置id为1的用户信息是一个json,同时也可以mset user:1:name zhangsan user:1:age 10 ...
这相当于将这个user的每个属性都分开设置到redis中了。
getset key value
先get 再set,当key不存在时,返回null 并设置这个key和value,当key存在时,返回key的值并用value覆盖之前的valuestring类型的使用场景,value除了可以是字符串还可以是数字,因此可以用到以下场景:
在redis中可以将List作为一个栈、队列、阻塞队列来实现。
所有的命令都是用L开头的
Lpush list one 1 2 3
给list左边添加一个或多个元素Rpush list value v1 v2 v3...
给list右边添加一个或多个元素Lpop list
从列表的左边弹出一个元素Rpop list
从列表的右边弹出一个元素,弹出后元素内容-1Lindex list 0
获取list中下标为0的元素Llen list
获取list长度Lrem list count value
表示移除list中count个value元素。Ltrim list start stop
表示根据下标截取队列rpoplpush list1 list2
将list1中最后一个元素移除,并将其放入list2中lset
将列表中指定下标的值替换为另一个值,更新操作,如果列表不存在或下标不存在会报错Linsert list befor/after value newvalue
往list中的value的before或after插入一个newvalue处插入一个值。set不能重复
sadd set v1 v2 v3....
往set集合中添加一个或多个元素,重复元素只能添加进一个smembers set
获取所有元素sismember set value
判断value是否存在scard set
获取set中元素的个数srem set value
将value移除set集合srandmember set count
随机返回count个数的元素,count默认1spop set count
从set中随机移除一个或count个元素smove set newset member
将set中的指定元素移动到newset中应用场景:
微博、b站 共同关注(并集)
sdiff set1 set2
差集sinter set1 set2
交集 共同关注就可以这么实现sunion set1 set2
并集hset hash key value key1 value1 ...
与string类似,命令以H开头,只不过值是k-vhget hash key1 key2...
hmset hash key value key1 value1 ...
多个操作hmget hash key1 key2...
hgetall hash
获取所有的键值对hdel hash key
删除指定的key的字段,对应的value也就没有了hlen hash
获取这个hash中有多少个键值对hexists hsah key
判断这个key是否存在hkeys hash
获取所有keyhvals hash
获取所有valuehincrby hash key 1
自增hdecrby hash key 1
自减hsetnx hash key
如果不存在可以设置,如果存在,则不能设置hset hash user:id:name zhangsan
,因此hash更适合存储对象,而string比较适合存储字符串zadd key 序号 value
zrange zset 0 -1
朋友的定位,附近的 人,打车距离,比如两地之间的距离等等
共六个命令
geoadd key 维度 经度 名称
添加地理位置。南北极无法添加,一般会下载城市地理数据,使用java程序一次性导入,例子GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
。经度和维度的范围超出会报错
geodist
m 表示单位为米。
km 表示单位为千米。
mi 表示单位为英里。
ft 表示单位为英尺。
如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。
georadius
如图,显示110 30 这个经纬度周围500km的城市
附近的人的原理就是这个,当我们将所有用户的位置信息加入redis后,某个用户查看周围范围(可指定)多少人(可指定)
georadiusbymember
找出位于指定范围内的元素,中心点是由给定的位置元素决定
geohash
了解一下 返回一个或多个位置元素的 Geohash 表示
原理
geo的底层实现是基于zset,因此我们可以使用zset的命令来操作geo的元素。如下图,这个china:city内的数据都是使用geo命令添加的,
参考文档
什么是基数?
A{1,2,3,6,7,8,9} B{a,3,5,4,6,1}.基数就是不重复的元素,因此这两个集合的基数就是9
简介:
Redis2.5.9版本更新了Hyperloglog数据结构
应用场景:统计网站访问量,同一个人多次访问也只计做一次
传统的做法:使用set保存用户id,计算set的size,这个方法的缺点就是耗费内存,并且我们的主要目的是计算访问量,而不是保存id
使用Hyperloglog:内存占用小,2^64的数据仅占用12KB;错误率0.81%很低,基本上可以忽略不计
命令如下图:
统计用户信息,活跃、不活跃,登录、未登录,打卡,两种状态的都可以使用BitMap
Bitmap 位图,使用二进制来进行记录,只有0和1两个状态的都可以这么做
具体我也不知道咋操作,参考官网文档
ACID:
redis的事物:
- 开启事物:multi
- 命令入队:
- 执行事物:execu
例如上图:multi命令开启事物,然后将一堆set、get命令加入队列QUEUED,最后执行命令exec,才将所有命令运行完
- 放弃事物:discard
异常:
由此可以看出,redis中事物是不保证原子性的,但是单条命令是保证原子性的。在这个例子中按照原子性的解释是所有命令都不能被执行,要成功全部成功,要失败全部失败。
锁:
悲观锁:认为任何时候都有可能出问题,因此在任何时候都要加锁
乐观锁:认为 一般不会出问题,所以不上锁。只有在特定的时候才上
使用watch实现乐观锁
举例:如下图,当我们有一个存款为100的时候,开启监视watch命令,然后开启事物,执行消费二十,然后给支出项增加二十,或者余额减去二十,然后提交事物,执行命令,这个时候是正常执行的没有问题。
当出现如下情况的时候,首先监视money,这个时候它的值是100,然后开启事物,消费10块钱,支出项增加10,然后在exec命令执行之前,另一个线程中修改了money的值,这个时候exec执行的时候发现money的值已经改变了,就会返回一个null,表示事物执行失败
那么如何解决这个问题呢?首先使用UNwatch命令解锁,将刚才出异常的锁释放掉,然后重新给 money加锁,重新开启事物,加入命令到队列,再exec,这个时候获取到的就是最新的money。
什么是jedis?
jedis是Redis官方推荐的java连接开发工具,使用java操作redis中间件,在springboot中使用redisTemplate操作,但是还是要对jedis十分了解才行。
jedis 操作redis的方法就是上面写的命令。例如:
public void testTx() throws JSONException {
JSONObject jsonObject = new JSONObject();
jsonObject.put("name","张三");
jsonObject.put("age","16");
//创建redis连接对象
Jedis jedis = new Jedis("127.0.0.1",6379);
//开启事物
Transaction multi = jedis.multi();
//给user添加乐观锁
jedis.watch("user");
try {
multi.set("testkey","testValue");
multi.set("user",jsonObject.toString());
//如果在事物执行的时候出现异常
//执行事物
multi.exec();
}catch (Exception e){
multi.discard();//出现异常放弃事物
}finally{
jedis.close();
}
在springboot2.x之后,原来使用的jedis被替换为lettuce,为什么替换呢?
redis:采用直连的方式,多线程操作不安全,如果想要避免不安全,就要使用jedis pool连接池,类似BIO模型 ,是阻塞的。
lettuce:采用netty,实例可以在多个线程中共享,不存在线程不安全情况,更像NIO模型
spring-boot-starter-data-redis
,这个启动器底层是使用的spring-data-redis
来连接redis的,springData也是spring的一个大型项目,包括jpa、jdbc、MongoDB、reds都是使用springdata进行连接。public class RedisAutoConfiguration {
public RedisAutoConfiguration() {
}
@Bean
@ConditionalOnMissingBean(
name = {
"redisTemplate"}
)//当我们的项目中没有redisTemplate的时候,才启用这个bean,也就是说我们可以重写一个redisTemplate类来覆盖当前这个类。
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
//并且,这里的泛型是
//还有就是我们在保存对象的时候,这些对象都是要序列化的,而这个默认redisTemplate并没有做过多的配置,因此大部分情况下我们都需要重写一个redisTemplate
RedisTemplate<Object, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean//由于开发中操作的string类型比较多,因此单独提出了一个stringRedisTemplate
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
//再来看一下redis的配置类
public class RedisProperties {
private int database = 0;//默认使用0数据库,我们可以使用命令select 下标的方式来切换使用的数据库
private String url;//连接redis服务的url
private String host = "localhost";//主机默认localhost
private String password;
private int port = 6379;
private boolean ssl;//是否开启了ssl(Secure Sockets Layer 安全套接字协议),如果开启,则设置为true
private Duration timeout;//连接超时时间
//下面这些事关于redis集群的相关配置
private RedisProperties.Sentinel sentinel;
private RedisProperties.Cluster cluster;
//在上面提到的,springboot2.x之后将jedispool替换为lettcupool,因此springboot默认使用的就是Lettuce,如果要使用redispool,则需要单独配置和加入依赖。
private final RedisProperties.Jedis jedis = new RedisProperties.Jedis();
private final RedisProperties.Lettuce lettuce = new RedisProperties.Lettuce();
public void testRedis(){
//springboot 中opsForxxx即表示操作某个类型,如下:
redisTemplate.opsForValue();//操作string类型
redisTemplate.opsForList();//操作List类型
redisTemplate.opsForHash();//操作map类型
redisTemplate.opsForSet();//操作set类型
...
//还有一些常用的操作,可以直接用redisTemplate进行
redisTemplate.multi(); //开启事务
redisTemplate.exec();//执行事务
redisTemplate.watch(...);//开启乐观锁
redisTemplate.discard();//关闭事务
}
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<String, Object> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
//使用json的方式序列化所有对象
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
//创建string的序列化器
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//设置所有的key都使用string类型的序列化器
template.setKeySerializer(stringRedisSerializer);
//设置所有的hash类型的key也是用string类型的序列化器
template.setHashKeySerializer(stringRedisSerializer);
//设置hash类型的value使用json序列化器
template.setHashValueSerializer(jackson2JsonRedisSerializer);
//设置所有的value都使用json序列化器
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
redis的配置文件redis.conf,这个文件中使用################### 模块名##############
这种方式将各个配置项分割开来,具体如下:
单位配置:不知道这玩意是干啥的,一般不动。配置大小写不敏感
INCLUDES,包含,意思就是可以把其他配置文件包含进来组成一个配置文件,这在你有标准配置模板但是每个redis服务器又需要个性设置的时候很有用。并且include 配置最好放在配置文件的最后一行?
# include .\path\to\local.conf
# include c:\path\to\other.conf
NETWORK 网络配置
GENERAL 通用
SNAPSHOTTING 快照,快照分rdb和aof
REPLICATION 主从复制
SECURITY 安全
vm_redis:0>config get requirepass //获取密码
1) "requirepass"
2) ""
vm_redis:0>config set requirepass 123456 //设置密码
"OK"
vm_redis:0>config get requirepass
1) "requirepass"
2) "123456"
vm_redis:0>ping
"PONG"
vm_redis:0>auth 123456 //使用密码登录
"OK"
CLIENTS 客户端配置
maxclients 10000 最大允许一万个客户端连接
maxmemory 配置redis的最大内存容量
maxmemory-policy noeviction 内存达到上限后的回收策略
从已经设置了过期时间的key中去选择
APPEND ONLY 模式 aof配置(了解,大部分情况下rdb已经足够使用,aof是对rdb的一个补充,并且性能不高,因此使用少)
参考文档
redis 是内存数据库,断电及失,因此需要持久化,默认使用RDB,一般情况下我们无需修改RDB配置,即可使用。
Redis会单独创建一个fork子进程来进行持久化,子进程中循环所有的数据,将数据写入到二进制文件中,会先将数据 写入到一个临时文件中,待持久化过程都结束了,在用这个临时文件替换上次持久化好了的文件。整个过程中,主进程是不进行任何IO操作的,确保极高的性能,如果需要进行大规模数据的回复,且对数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加高效。RDB的去电就是最后一次持久化后的数据可能丢失。
RDB保存的文件就是dump.rdb
当我们修改了配置文件后,直接使用save命令就可以保存修改
关于快照的配置都在SNAPSHOTTING 项中
config get dir
如果在该目录下存在,就会自动恢复其中的数据RDB的优点:
什么事aof?
aof是将我们所有的命令都记录下来,然后在恢复的时候再重新执行一次,并且只记录写操作的命令,读命令不会记录。只追加文件。因此aof的速度会慢一些,尤其是大数据的情况下,恢复数据也需要很久
aof保存的文件是 appendonly.aof
AOF (配置文件中 APPEND ONLY Model 项)配置:
redis-chech-rdb
,另一个是redis-chech-aof
,因此如果出现这种情况,我们就可以使用这两个工具修复文件,如下下图AOF优点:
与消息中间件MQ中发布订阅一样,是一种小心通信模式,发送者pub发送消息到channel,订阅者sub从channel获取消息,redis实现的发布订阅相比MQ要简单一些,主要是几个命令。主要的应用场景例如微博微信的关注等等。redis客户端可以订阅任意数量的频道(channel)
例子:
#订阅者,订阅了channel01 这个频道,然后监听该频道,当有发送者发送消息的时候,这个监听的控制台就会打印出来。
192.168.0.113:6379> SUBSCRIBE channel01 #订阅者订阅 channel01频道
Reading messages... (press Ctrl-C to quit) #开启监听,等待读取信息,也就是说频道是订阅者建立的,因为我们可以参考下面例子2中的命令,发现当我们往一个不存在的频道channelxx中发送消息的时候,是不成功的,返回integer为0
1) "subscribe"
2) "channel01"
3) (integer) 1 # 表示订阅成功,处于监听状态
1) "message"
2) "channel01"
3) "one message" #第一次收到消息,发送者就是下面这个发布者,当发送者发送完成后,这里显示频道和message
1) "message"
2) "channel01"
3) "tow message hello world"
#发布者往channel01频道发送消息
192.168.0.113:6379> PUBLISH channel01 "one message"
(integer) 1
例子2
#发布者往一个不存在的频道发送信息
192.168.0.113:6379> PUBLISH channelxx "xxxxx message"
(integer) 0
JedisPushSub类
Jedis中的JedisPubSub类是Jedis的一个抽象类,此类定义了public/subscribe的回调方法,通过继承JedisPubSub类重写回调方法。实现java中Redis的发布订阅。当Redis发生发布或者订阅的相关事件时会调用这些回调方法,只在回调方法中实现自己的业务逻辑。
onMessage():发布者发布消息时,会执行订阅者的回调方法onMessage()接收发布的消息,在此方法实现消息接收后进行自定义的业务逻辑处理。
//订阅者
public class RedisSubscriber extends JedisPubSub {
@Override
public void onMessage(String channel, String message) {
SimpleDateFormat df = new SimpleDateFormat("yyyy MM dd HH:mm:ss");
System.out.println("订阅者:订阅频道["+channel+"],收到消息["+message+"],时间:"+df.format(new Date()));
}
public static void main(String[] args) {
System.out.println("启动订阅者");
//创建Jedis
Jedis jedis = new Jedis("192.168.40.133", 6379);
//创建订阅者
RedisSubscriber redisSubscriber = new RedisSubscriber();
//订阅频道
jedis.subscribe(redisSubscriber,"badaodechengxvyuan");
}
}
//发送者,发送者可以使用redis-cli客户端使用命令行的方式发送,也可以新建一个项目,如下,在main方法中发送
public class Publisher {
public static void main(String[] args) {
System.out.println("开始发布......");
//创建Jedis
Jedis jedis = new Jedis("192.168.40.133", 6379);
//发布消息
jedis.publish("badaodechengxvyuan", "紧急通知:...");
System.out.println("消息发送完毕......");
}
}
redis是通过publish、subscribe、和psubscribe等命令实现发布和订阅功能
通过subscribe命令订阅某频道后,redis-server里维护了一个 字典,字典的键就是一个个的channel(通道、频道),而字典的值则是一个链表,链表中保存了所有订阅这个channel的客户端。subscribe命令的关键,就是讲客户端添加到给定channel的订阅链表中。
通过publish命令想订阅者发送消息,redis-server会使用给定的频道作为键,在他所维护的channel字典中查找记录了订阅这个频道的所有客户端的链表,便利这个链表,将消息发布给所有订阅者。
pub/sub在字面上理解就是发布(publish)与订阅(subscribe),在redis中,你可以设定对某个key值进行消息发布及消息订阅,当一个key值上进行了消息发布后,所有订阅它的客户端都会受到相应的消息,这一功能最明显的用法就是用作实时消息系统,例如群聊等
什么是redis主从复制
就是将一台redis服务器的数据,复制到其他的redis服务器,前者称为主节点(master/leader,主节点不用配置,redis默认单机就是主节点),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。master以写为主,slave以读为主。主从复制,读写分离。
首先是集群环境搭建,一般最低一主二从,因为redis的哨兵模式有个从机的分配策略,如果一主一从就没发分配,下面我们模拟一个一主二从的环境。
步骤:
192.168.0.113:6379> info replication
# Replication
role:master # 角色主机
connected_slaves:0 # 连接的从机 0个
master_replid:ac2ce59a7afcd52e3860e7a1083e304a0214ee29
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
redis-server redis6379.conf
分别启动三个不同端口的服务ps -ef|grep redis
查看启动的redis服务,出现下图表示三个redis服务器启动成功说明:我们这里使用的是单机集群,多机集群怎么配不知道,猜测应该是在从机的配置文件中配置指向主机的地址
这个时候我们还没有配置主从复制,因此上面三个服务都是主节点,默认情况下,每台redis服务都是主节点
一般情况下只需要配置从机,不需要配置主机。我们只需要在从机命令行窗口输入命令slaveof 127.0.0.1 6379
即可,使用命令配置的方式是暂时的,如果重启就失效,推荐使用配置文件的方式,如下:
使用配置文件的方式
在redis.conf文件中有个叫replication的模块,该模块就是主从复制的配置
slaveof
和命令行一样,配置该项,将主机的地址和端口配置即可
masterauth
如果主机有密码,则在这里配置密码
slave-serve-stale-data yes
该项表示与主机断开连接后的处理措施,yes表示断开后依然启动服务,只不过数据有可能是旧数据,如果主机从来没有同步过来数据,则该从机有可能是空的。如果是no,则返回与‘主机同步中’的错误信息
配置完成后输入命令info replication
查看如下图
可以看出这里的信息role已经发生了变更,并且主机查看显示从机也不为0.至此主从复制配置完成
补充:
slave-serve-stale-data yes
的配置策略。(启用哨兵模式后就不会这样)还有另一种主从配置
对应到slaveof中就是6379为主机,6380Slaveof6379,6381Slaveof6380,这种配置中这个6380即是主机又是从机,那么如果这个时候6379宕机了6380会怎么样,使用命令info replication
查看后发现,这个6380依然是从机。因此上面两种配置在我们工作的时候多不会用。
在没有哨兵模式之前,我们主机宕机之后,需要手动指定主机,使用命令Slaveof no one
,表示没有任何一个从机,我就是主机。然后在给其他从机重新Slaveof 到新的主机。如果这个时候原来的主机又上线了,那么他依然是个主机。
Redis集群的Spring Boot连接方式非常简单,只需要在application.properties配置文件中把之前单机配置的ip和端口号注释掉,换成集群的nodes节点即可,用逗号分隔:
#spring.redis.host=192.168.253.129
#spring.redis.port=6379
spring.redis.cluster.nodes=192.168.253.129:7001, 192.168.253.129:7002, 192.168.253.129:7003, 192.168.253.129:7004, 192.168.253.129:7005, 192.168.253.129:7006
这个是重点
什么是哨兵模式?
哨兵模式就是自动选取主机的方法。在上面的案例中我们使用一主二从的方式配置了redis集群,可以发现如果当主机宕机,就会存在一些问题,例如无法写数据等等,哨兵模式就是自动切换主机。
哨兵默认端口26379
与redis类似,在解压文件中有个与redis.conf 同级目录的文件sentinel.conf,这个文件就是redis哨兵模式的配置文件。与redis-server同级的redis-sentinel 就是哨兵模式的服务进程。哨兵模式是一个单独的进程,用来监视redis-server。
sentinel monitor myredis 127.0.0.1 6379 1
表示sentinel monitor 被监控的名称(自己随意) 主机 端口;后面这个1代表主机挂了,哨兵会投票选取一个从机作为主机(投票算法) 这个是最基础最核心的配置redis-sentinel sentinel.conf
使用配置文件的方式启动哨兵的两个作用
哨兵模式也可以集群,如果我们配置单个哨兵来监视所有主从集群,一旦哨兵所在的主机宕机,那么哨兵也就不存在了,因此也可以配置哨兵集群,哨兵之间不仅监视redis,还要各自监视。
假设主库宕机,哨兵1先检测到这个结果,系统并不会马上进行切换,仅仅是哨兵1认为主服务器不可用,这个现象称为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值的时候,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover(故障转移)操作。切换成功后就会通过发布订阅模式,让各个哨兵吧自己监视的从服务器切换主机,这个过程称为客观下线。
哨兵集群的配置与redis的集群配置类似,在配置文件中分别指定哨兵的端口,然后以配置文件的方式启动。
缓存雪崩是指在某个一时间段,缓存集中过期失效
例如快要双十一0的抢购高峰的时候,这个时候商品时间比较几种的放入了缓存中,假设缓存一小时,那么到了1点的时候,这批商品的缓存信息失效,对这批商品的查询都会落入到数据库中,对数据库而言,就会产生周期性的波峰压力。有可能会引起数据库挂掉的情况。
**笔记来源 **
bilibili狂神说-redis学习视频