博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redis的基本环境配置以及基本使用入门
阅读量:2047 次
发布时间:2019-04-28

本文共 16697 字,大约阅读时间需要 55 分钟。

文章目录

Redis是什么

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

Redis能做什么

1、内存存储、持久化,内存中是断电即失、所以说持久化很重要( rdb、 aof )

2、效率高,可以用于高速缓存
3、发布订阅系统
4、地图信息分析
5、计时器、计数器(浏览量!)

Redis使用之前的准备工作

将Redis安装到本地的Linux或者远程的服务器都可以,我这里是选择将Redis安装到了阿里云服务器,可以通过宝塔一键傻瓜式安装,具体教程可以观看。也可以通过自己下载对应的Redis的Linux版本的安装包,通过Xshell和Xftp自行安装。如果是通过宝塔安装完成Redis之后,Redis会存放到以下目录:

在这里插入图片描述
因为Redis是用C++编写的,我们使用Xshell连接到远程服务器之后,通过cd命令进入到这个目录,安装一些基本的使用环境,通过:
yum install gcc-c++
yum install tcl(redis6.0版本以上需要使用这个)
安装完成之后,我们通过make(宝塔傻瓜式安装好像不用make,因为他已经帮我们准备好了所有的环境,具体使用可以看这篇文章上面一点的一个超链接,但是如果是自己通过下载安装包拷贝的形式的话,需要make一下)将一些环境给配置一下。配置完成后,我们可以通过
make install查看安装情况,出现如下代码则显示安装成功。
在这里插入图片描述

安装完成之后,我们为了避免直接修改此文件,应该将该目录下的redis.conf文件复制粘贴一份,粘贴到我们的/usr/local/bin/xxx的目录下,可通过Xftp直接复制粘贴,然后在bin目录下新建一个文件夹用于存放我们的redis配置文件。如图所示:

在这里插入图片描述
随后我们通过shell命令行vim redis.conf或者直接用Xftp右键修改,将
daemonize 修改为yes,设置为默认启动,因为redis不是默认启动的(使用宝塔傻瓜式安装好像这里默认就是yes不用修改)在这里插入图片描述
到这里基本准备环境就准备好了,我们可以启动redis了,在/usr/local/bin目录下,我们通过前面一步自己配置的conf文件启动我们的redis,通过shell输入:
redis-server 自己的目录/redis.conf
redis6.0版本之后启动成功是不会有提示的,所以到这一步的小伙伴们不要担心是不是自己哪一个步骤除了问题导致启动失败。然后我们链接我们的redis服务器,通过:
redis-cli -h 端口号 -p 6379
其中由于-h是默认的使用的本机,所以因此可以不用写上去,-p是我们的redis服务器,6379是我们的默认端口号。
回车之后,我们通过Ping命令测试是否连接成功,如果返回的是pong,则表示连接成功,如图所示:
在这里插入图片描述
通过keys *可以查看所有的key值。
在这里插入图片描述

如果我们想要查看我们的进程是否开启,可以通过

ps -ef | grep 进程
查看,如:
在这里插入图片描述
如果我们要关闭我们的redis服务,可以通过
shutdown 然后 exit即可,如:
在这里插入图片描述
再次查看进程,会发现该进程其实已经是被终结了。 至此,我们的基本准备环境已经完成了。

Redis-benchmark压力测试工具

相关参数:

在这里插入图片描述

Redis基础知识

1、redis的数据库有16个,默认使用的是第0个。

在这里插入图片描述
我们可以通过select切换数据库,通过DBSIZE查看当前库大小如图所示:
在这里插入图片描述
如果我们要清空当前数据库的key信息,可以通过
flushdb清除当前库或者通过flushall清除所有的数据库内容

2、redis是单线程的,是基于内存操作的。瓶颈是机器内存和网络带宽。(redis6.0以上是可以开启多线程的)

Redis的五大数据类型

它支持多种类型的数据结构,如字符串(strings)散列(hashes)列表(lists)集合(sets)有序集合(sorted sets) 与范围查询, bitmapshyperloglogs地理空间(geospatial) 索引半径查询。Redis 内置了 复制(replication),LUA脚本(Lua scripting),LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence),并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

Redis-key

在这里插入图片描述

String类型

append key value

往key对应的字符串里面追加字符串。如果当前key不存在则相当于set key value
strlen key
可以查看当前key的字符串长度。
incr key
相当于i++的操作,可以用于网页浏览量的使用
decr key
相当于i–
incrby key value(增长量)
一次增加多少增长量
decrby key value(减少量)
一次减少多少的减少量
getrange key start(起始位置) end(结束位置)
获取字符串范围里面的值,例如我有个字符串key名为name,value值为"hello,world",getrange name 0 3,就是截取当前字符串0号索引到3号索引的字符,输出的结果是hell。
getrange key start -1表示的是获取全部字符串,同get key作用
setrange key start(起始索引位置) value(要替换的字符串)
替换指定位置的字符串
在这里插入图片描述
setex key outtime(过期时间) value(字符串)
设置一个存活时间为outtime的key键值对。
setnx key value
不存在设置(常用于分布式锁),如果不存在则建立,存在的话就创建失败。
在这里插入图片描述
mset key1 value1 key2 value2 ……
批量设置
mget key1 key2 key 3……
批量获取
在这里插入图片描述
开发中常用的String存对象 写法如下图所示:
在这里插入图片描述
getset key
先get然后再set
在这里插入图片描述
其中value除了可以是字符串,也还可以是数字。

List类型

在redis里面,我们可以把list变成栈、队列、阻塞队列。命令前面加L表示是List类型,R是特殊的List类型

Lpush list从左边插入队列
Rpush list从右边插入队列
在这里插入图片描述
具体的执行流程:
在这里插入图片描述
Lpop list
从左边移除第一个元素
Rpop list
从右边移除第一个元素
在这里插入图片描述
Lindex根据下标取出对应的元素
在这里插入图片描述
Llen
返回List长度
在这里插入图片描述
Lrem
移除指定的个数的value,精确匹配
在这里插入图片描述
trim list start end修剪,通过下表截取指定长度,保留想要的元素
在这里插入图片描述
rpoplpush
移除list最后一个元素,加入新的list集合中
在这里插入图片描述
lset
根据指定下标的值更新为另一个值,相当于update操作
在这里插入图片描述
linsert
插入操作,将某一个具体的value插入到某个元素前面或者后面
在这里插入图片描述
小结:

⚫ list其实是一个链表,可以通过linsert在某个具体元素的前面或后面插入,也可以通过lpush,rpush在首或者尾插入元素。

⚫ 可灵活变换,Lpush,Rpop就成了消息队列。Lpush,Lpop就成了

Set类型

sadd

往set集合里面添加值
smembers
查看set集合所有的值
sismember
判断该元素是否在set集合里
在这里插入图片描述
scard set
获取集合中元素的个数
在这里插入图片描述

srem

移除集合具体元素
在这里插入图片描述
srandmember
随机获取set集合中的一个元素。可以用于随机获取

spop

随机删除集合的元素

smove set1 set2(目标集合) key

移动一个指定的元素到另外一个集合
在这里插入图片描述

sdiff set1 set2

以set1为基准比较set1和set2,找出set1差集。

sinter set1 set2

交集,找出set1,set2并集的部分

sunion set1 set2

并集
在这里插入图片描述

Hash类型

Map集合,村的是key—value的形式,相当于key value(key,value>。

hset key key,value
在这里插入图片描述
hdel key key
删除某一个key的某一个具体字段
在这里插入图片描述
hlen
获取哈希表字段数量

hexists

判断hash中指定字段是否存在
在这里插入图片描述
hkeys key
只获取所有字段
hvals key
只获取所有值
在这里插入图片描述
incr
decr
在这里插入图片描述

Zset有序集合

zadd key source value

添加操作,其中source是分数,可以理解为权值,主要用于排序在这里插入图片描述
zrangebyscore key min max
排序
在这里插入图片描述

zrem key value

移除元素
在这里插入图片描述
zcard key
查看集合元素个数
在这里插入图片描述

zcount

查看区间内成员个数
在这里插入图片描述

小结:

具体应用,zset可以用于排行榜实时热搜的实现。
具体的使用和set无异,差别是多了一个权重,一个scores分数而已。

三大特殊类型

Geospatial地理位置

Geoadd

添加地理位置
在这里插入图片描述
getpos
获取指定城市的经度纬度,获得当前定位。
在这里插入图片描述
geodist
返回两个坐标之间的距离。距离单位有m米,km千米,mi英里,ft英尺
在这里插入图片描述
georadius
以给定的经纬度为中心,查找某一半径中的具体元素
在这里插入图片描述
在这里插入图片描述
GEORADIUSBYMEMBER
找出指定元素周围的元素
在这里插入图片描述

小结:

Geo的底层使用原理其实是zset,因此我们要删除某些元素,我们可以通过zrem移除:
在这里插入图片描述

Hyperloglog基数统计

常用于页面浏览量统计

在这里插入图片描述

Bitmaps

非0即1,操作二进制位来进行储存。

在这里插入图片描述

Redis的基本事务操作

Redis单条命令是保证原子性的,但事务不保证原子性,没有隔离级别的概念。Redis事务的本质其实就是一组指令的集合,一个事务中的所有命令都会被序列化,按顺序执行。

开启事务:

命令入队:
执行事务:(注意,执行完事务之后,当前事务就已经结束了,如果还要开启事务,还要重新输入multi命令)
在这里插入图片描述
放弃事务:
在这里插入图片描述
异常事务:
编译时异常,所有的代码都不会被执行。
在这里插入图片描述
运行时异常:
错误的指令不会执行,不会影响其他指令的正常执行。
在这里插入图片描述

Redis实现乐观锁

通过watch监视器监视,这里的watch其实就相当于上锁。具体用法:watch key

正常执行的情况:
在这里插入图片描述
异常操作
在这里插入图片描述

如何解决?

如果发现事务执行失败,就先通过unwatch解锁,然后再通过watch加锁。检查版本看看是否发生了修改,再进行execute。

Jedis

连接远程服务器

是Java来操作redis的中间件,通过Jedis可以对redis进行操作。具体操作步骤如下:

第一步、引入相关测试Jar包

redis.clients
jedis
3.2.0
com.alibaba
fastjson
1.2.73

第二步、编写测试用例

这里由于我使用的是远程服务器进行测试,因此这里的ip写各自的ip即可,如果是安装在本地的服务器,可以直接使用127.0.0.1进行测试。

public class testPing {
public static void main(String[] args) {
Jedis jedis = new Jedis("your ip",6379); System.out.println(jedis.ping()); }}

如果使用的远程服务器,运行到这里,可能又会报错,会显示

Failed connecting to host IP 6379
提示报错我们的访问被拒绝了,其实很简单改。

首先我们得在阿里云服务器安全组,开放redis6379的端口,如图所示:

在这里插入图片描述
第二步,我们得修改相对应的redis启动配置文件,具体要修改的地方有两个,第一个是将bind 127.0.0.1进行注释,允许所有IP进行访问,或者将其修改为0.0.0.0。第二个是将保护模式关闭,将protected-mode no设置为no。
第三步,将防火墙打开,允许6379访问,由于我使用的是宝塔安装,因此我管理对应的防火墙端口非常方便,只需要手动添加放行即可,如图所示:
在这里插入图片描述
如果不是使用宝塔安装的朋友,可以参考这篇文章:
最后,我们在客户端进行连接,如果响应为PONG,则连接成功啦。
在这里插入图片描述
但是为了安全,我们最好还是为我们的redis设置一个密码,具体的设置流程可以参考这篇文章:
具体的操作API同上文讲的五大基本类型无异,无非是通过jedis操作罢了,下面展示测试结果:
在这里插入图片描述
在这里插入图片描述

事务操作

public class testTX {
public static void main(String[] args) {
Jedis jedis = new Jedis("Your IP",your port); jedis.flushDB(); JSONObject jsonObject = new JSONObject(); jsonObject.put("username","redis"); jsonObject.put("password","123"); //开启事务 Transaction multi = jedis.multi(); String result = jsonObject.toJSONString(); jedis.watch(result);//加锁以确定result没被修改 try {
multi.set("key1",result); multi.set("key2",result); multi.exec();//执行事务 } catch (Exception e) {
multi.discard();//放弃事务 e.printStackTrace(); }finally {
System.out.println(jedis.get("key1")); System.out.println(jedis.get("key2")); jedis.close();//关闭客户端 } }}

Redis整合SpringBoot

首先说明,在springboot2.x以后,我们所导入的springboot-redis整合包,他采用的不再是jedis操作redis,而使用的是lettuce操作redis。这样做的目的是因为jedis采用的是直连,多个线程操作是不安全的,如果要避免不安全,得使用jedis pool线程池。而采用lettuce的话,它是用netty实现的,实例可以在多线程中共享,不存在线程不安全的情况。

整合过程

整合步骤,通过springboot脚手架,创建一个基本项目。

在这里插入图片描述
创建完项目后,因为使用的是springboot整合的redis,springboot帮我们整合了redis的配置文件,但是如果我们想自己配置,但是又不知道有什么可以配置,可以自己去寻找相关的配置文件。如下所示
在这里插入图片描述
在这里插入图片描述
通过ctrl+鼠标左键,点击进入该配置文件
在这里插入图片描述
我们就找到我们的redis配置文件啦

源码分析:

@Bean	@ConditionalOnMissingBean(name = "redisTemplate")//我们可以自定义一个叫redisTemplate的类来替换这个类,使这个类失效,因为这个类很多都没有设置,默认序列化格式是jdk序列化	@ConditionalOnSingleCandidate(RedisConnectionFactory.class)	public RedisTemplate
redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//两个泛型都是obj,obj形式,后面得强转为str,obj形式 //默认redisTemplate没有过多设置,redis对象都需要序列化 RedisTemplate
template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean @ConditionalOnSingleCandidate(RedisConnectionFactory.class) public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; }

整合测试

@SpringBootTestclass RedisSpringbootApplicationTests {
@Autowired private RedisTemplate redisTemplate; @Test void contextLoads() {
//opsFor 操作不同数据类型 redisTemplate.opsForValue().set("key1","test"); System.out.println(redisTemplate.opsForValue().get("key1")); //操作数据库,获取redis连接对象// RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();// connection.flushDb();// connection.flushAll(); }}

在这里插入图片描述

自定义RedisTemplate

前面说到我们的RedisTemplate默认配置其实有很多都是没有配置的,包括我们的序列化设置,如果使用的是默认的序列化配置,我们通过redis的keys *操作,会看到已经被转义了的value值,如上一步测试操作里,我set的value明明是test,但是我在redis服务器get的值如图所示:

在这里插入图片描述
所以,我们要配置一个自己的配置类。

@Configurationpublic class RedisConfig {
@Bean public RedisTemplate
redisTemplate1(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate
template = new RedisTemplate<>(); //设置连接方式为默认的lettuce template.setConnectionFactory(redisConnectionFactory); //所有的object对象都要经过该json序列化 Jackson2JsonRedisSerializer
objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //对序列化对象进行转义,确保不出现诸如\xac\xed\x00\x05t\x00\这种格式的情况 ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL); objectJackson2JsonRedisSerializer.setObjectMapper(om); //String字符串类型的序列化方式 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); /** * 此处是设置各数据类型key的序列化格式 * */ //key采用String的序列化方式 template.setKeySerializer(stringRedisSerializer); //hash的key采用String序列化方式 template.setHashKeySerializer(stringRedisSerializer); //value序列化采用的是jackson template.setValueSerializer(objectJackson2JsonRedisSerializer); //hash的value采用的是jackson template.setHashValueSerializer(objectJackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; }}

测试:

POJO类:

@Component@Data@NoArgsConstructor@AllArgsConstructor/** * 序列化对象,不然的话在通过redisTemplate传对象的时候传不了 * */public class user implements Serializable {
private String name; private String password;}

测试类:

@SpringBootTestclass RedisSpringbootApplicationTests {
@Autowired @Qualifier("redisTemplate1") private RedisTemplate redisTemplate; @Test void test(){
user user = new user("learn", "good"); redisTemplate.opsForValue().set("user",user); System.out.println(redisTemplate.opsForValue().get("user")); }}

Redis配置文件详解

持久化的RDB操作

因为redis是基于内存操作的,断电即失,因此我们需要将相关的数据持久化操作。 Redis会单独创建( fork )-个子进程来进行持久化

,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何I0操作的。这就确保了极高的性能。如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比A0F方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
我们默认的就是RDB , -般情况下不需要修改这个配置!rdb保存的文件是dump.rdb都是在我们的配置文件中快照中进行配置的!
在这里插入图片描述
我们可以去定制自己的保存规则,在redis.conf文件里面修改即可,如下图所示。
在这里插入图片描述
默认情况下,有三种情况会触发我们的RDB操作,第一个是save规则,第二个是flushAll操作,第三个是exit退出redis。
那么,我们如何恢复rdb文件呢?其实只需要放到redis.conf的启动目录下就可以了,即bin目录下即可。

持久化的AOF操作

一个文件将我们所有的操作记录下来,恢复的时候就将该文件重新执行一遍。默认是不开启的,需要手动开启。

在这里插入图片描述
修改策略
在这里插入图片描述

Redis发布订阅

订阅端

127.0.0.1:6379> subscribe jieshouduan //订阅一个消息的接收端Reading messages... (press Ctrl-C to quit)1) "subscribe"2) "jieshouduan"3) (integer) 1//等待读取推送的信息1) "message"//消息2) "jieshouduan"//哪一个频道的消息3) "nihao"//具体消息1) "message"2) "jieshouduan"3) "hello,redis"

发送端

127.0.0.1:6379> publish jieshouduan "nihao"//发送端需要指定具体的接收端名称,后面接的具体消息(integer) 1127.0.0.1:6379> publish jieshouduan "hello,redis"(integer) 1

在这里插入图片描述

Redis主从复制

主从复制,是指将一台Redis服务器的数据 ,复制到其他的Redis服务器。前者称为主节点(master/leader) ,后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点。Master以写为主, Slave 以读为主。默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。

redis的主要作用:
在这里插入图片描述

环境配置

查看当前库信息:

127.0.0.1:6379> info replication# Replicationrole:master//主机connected_slaves:0//从机master_replid:1b577a2810ea61d1f05cbabdaadc18e804c920c9master_replid2:0000000000000000000000000000000000000000master_repl_offset:0second_repl_offset:-1repl_backlog_active:0repl_backlog_size:1048576repl_backlog_first_byte_offset:0repl_backlog_histlen:0

要实现主从复制,主要有以下几个步骤:

第一步:复制conf文件
在这里插入图片描述
第二步,依次修改每个config的文件内容,主要修改的有如下几个:
1、端口
2、pid名字
3、log文件名字
4、dump.rdb名字

第三步,通过redids-server启动服务,查看进程,如果启动了三个进程,则配置成功

在这里插入图片描述

一主二从

默认情况,每台Redis都是主节点,一般情况下只用配置从机就可以了。一主(6379),二从(6380,6381),从机通过SLAVEOF host port即可。通过info replication可以查看是否配置成功。需要注意的是,如果要配置的主机是有密码认证的,需要在从机的配置文件中修改masterauth 主机密码。

127.0.0.1:6379> info replication# Replicationrole:masterconnected_slaves:2slave0:ip=127.0.0.1,port=6380,state=online,offset=28,lag=0slave1:ip=127.0.0.1,port=6381,state=online,offset=28,lag=0master_replid:12c74a12389a3f02b53582ae27dc655293848366master_replid2:0000000000000000000000000000000000000000master_repl_offset:28second_repl_offset:-1repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:1repl_backlog_histlen:28127.0.0.1:6379>

但是这种通过命令配置的主从机,只是暂时的,真实的情况我们要配置的信息其实应该是永久的。需要在配置文件的REPLICATION里面配置

在这里插入图片描述
其中,主机的信息,从机中可以保存。主机只管写,从机只管读。主机断开连接,从机依旧执行,但是从机依然只能读操作。主机回来了,依然可写,从机依然能读到写的信息。如果是通过命令SLAVEOF配置的主从机,是暂时的,从机断开重连就又是主机。
在这里插入图片描述
通过手动命令,当主机宕机了,从机可以通过命令SLAVEOF NO ONE自己升级为主机,其他节点可以手动重连到这个主机。但是这个时候如果主机重连,升级的主机并不会自动变为从机,还是得手动配置。

哨兵模式

其实就是手动版的升级自动版切换。哨兵模式能够后台自动监控主机是否故障,如果故障了则通过投票数自动将从库变为主库。哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应.从而监控运行的多个Redis实例。

在这里插入图片描述
当然,一个哨兵也可能会出现’‘死亡’'的情况,因此,一般的情况下,我们的哨兵也是会有多个
在这里插入图片描述
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象称为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。

代码实现:

第一步、配置哨兵配置文件sentinel.conf,名字不能写错。如果主机配置了密码的,此处还要配置多一个密码信息。

//sentinel monitor 被监控的名称 IP 端口 1代表主机挂了,哨兵投票选举主机sentinel monitor myredis 127.0.0.1 6379 1sentinel auth-pass master(这里的名字是上面这一行你自定义的名字,例如我的名字是myredis) yourpassword

第二步、启动哨兵

[root@username bin]# redis-sentinel yourconfig/sentinel.conf

出现如下界面则配置成功:

11049:X 09 Dec 2020 16:18:58.155 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo11049:X 09 Dec 2020 16:18:58.155 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=11049, just started11049:X 09 Dec 2020 16:18:58.155 # Configuration loaded                _._                                                             _.-``__ ''-._                                                   _.-``    `.  `_.  ''-._           Redis 6.0.9 (00000000/0) 64 bit  .-`` .-```.  ```\/    _.,_ ''-._                                    (    '      ,       .-`  | `,    )     Running in sentinel mode |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379 |    `-._   `._    /     _.-'    |     PID: 11049  `-._    `-._  `-./  _.-'    _.-'                                    |`-._`-._    `-.__.-'    _.-'_.-'|                                   |    `-._`-._        _.-'_.-'    |           http://redis.io          `-._    `-._`-.__.-'_.-'    _.-'                                    |`-._`-._    `-.__.-'    _.-'_.-'|                                   |    `-._`-._        _.-'_.-'    |                                    `-._    `-._`-.__.-'_.-'    _.-'                                         `-._    `-.__.-'    _.-'                                                 `-._        _.-'                                                         `-.__.-'                                               11049:X 09 Dec 2020 16:18:58.156 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.11049:X 09 Dec 2020 16:18:58.156 # Sentinel ID is xxxxxxxxxxxxxxxxxxx(我省略了)11049:X 09 Dec 2020 16:18:58.156 # +monitor master myredis 127.0.0.1 6379 quorum 111049:X 09 Dec 2020 16:18:58.156 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6379//我的从节点11049:X 09 Dec 2020 16:18:58.160 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6379//我的从节点

如果这个时候主机宕机了,会自动重新选择一个主机,但是并不是说宕机了就会马上被看到,他需要一定的时间。此时如果主机重连的话,就会变成从机。

在这里插入图片描述

缓存穿透和雪崩

缓存穿透(查不到)

什么是缓存穿透?

缓存穿透的概念很简单,用户想要查询一、一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中(秒杀! ) , 于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。

解决?

1、布隆过滤器

对所有可能查询的参数以hash的形式储存,在控制层校验,不符合就丢弃在这里插入图片描述
2、缓存空对象
当储存层不命中的时候,即使返回的空对象也会被储存起来,同时设置一个过期时间,之后哦再访问这个数据就会从缓存中获取。
在这里插入图片描述

缓存击穿(量太大,缓存过期,一个key)

1、什么是缓存击穿

这里需要注意和缓存击穿的区别,缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。
2、解决方案
设置热点数据永不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题。
加互斥锁
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务 ,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。这个时候只需要等待回写缓存key即可。

缓存雪崩(大量key)

1、 什么是缓存雪崩?

缓存雪崩,是指在某个时间段,缓存集中过期失效。Redis宕机!产生雪崩的原因之一,比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。 那么到了凌晨一点钟的时候 ,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
2、解决方案
redis集群
搭建redis集群,提高可用性。
限流降级
在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
数据预热
数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key ,设置不同的过期时间,让缓存失效的时间点尽量均匀。
设立随机过期时间
随即过期时间避免缓存雪崩。

转载地址:http://ycqof.baihongyu.com/

你可能感兴趣的文章
6月15日-健身16
查看>>
6月24日-健身20
查看>>
6月28日-健身21
查看>>
7月4日-健身23
查看>>
7月18日-自己健身1
查看>>
会心一笑和喋喋不休
查看>>
超级英雄
查看>>
夏洛很幸福
查看>>
成长背后的惨痛代价
查看>>
一段永远无法磨灭的记忆
查看>>
2017年4月28日lab talk
查看>>
面试前有用的突击
查看>>
6月13日-健身15
查看>>
6月17日-健身17
查看>>
6月20日-健身18
查看>>
有的人遇见就是一生
查看>>
冒险的勇气
查看>>
等待中邂逅命运
查看>>
北方姑娘初见海
查看>>
6月22日-健身19
查看>>