redis从安装到三主三从集群

文章目录

一、为什么要使用Redis

1、读写的二八原则

  大多数场景下用户的写操作次数远远小于读操作次数,例如:用户使用淘宝的时候,绝大部分时间是查询商品,下单购买的操作频率相对较低,将频繁读取的数据,写入到reids中,可以减少读取数据库的次数,降低数据库的负载,同时也能加快读取速度

2、信息的统一管理

  当系统部署多个节点的时候,每个节点的缓存数据独立管理,会导致系统之间的数据出现不一致,交互不及时的情况,使用redis统一对这部分数据进行关联,可以降低维护代价和通知代价

二、常见缓存方案的对比

EhcacheMemcacheRedis
优点缺点优点缺点优点缺点
基于java开发不支持集群key-value存储无法容灾数据结构丰富单线程 (某些时候是优势)
基于JVM缓存不支持分布式内存使用率高无法持久化可持久化单核
简单、轻巧、方便多核、多线程主从同步、故障转移

三、安装redis

1、下载redis安装包、上传linux服务器

下载地址:https://redis.io/download

2、安装依赖

yum install gcc-c++

3、解压安装包

tar -zxvf redis-5.0.5.tar.gz

4、进入文件夹、编译并安装

cd redis-5.0.5
make && make install

5、修改redis的核心配置文件

在redis根目录下

#打开配置文件进行修改
vim redis.conf

修改配置

#后台运行
daemonize yes
#工作目录,一定是个目录,不是文件(需要自己创建文件夹)
dir /usr/local/redis/working
#可以访问redis的ip(这里表示所有ip都可以访问)
bind 0.0.0.0
#redis的密码(需要自己添加这个配置项,严重的后门)
requirepass 123456
#redis的端口
port 6379
#redis启动的进程号保存的位置
pidfile /var/run/redis_6379.pid

6、修改redis的启动脚本

在redis的utils目录下

#复制到init.d目录下为方便开机启动
cp redis_init_script /etc/init.d/
cd /etc/init.d/
vim edis_init_script

修改配置

#redis的端口(建议在redis.config中修改)
REDISPORT=6379
#指定redis的服务启动文件
EXEC=/usr/local/bin/redis-server
#指定redis的客户端启动文件
CLIEXEC=/usr/local/bin/redis-cli

#redis启动的进程号保存的位置(建议在redis.config中修改)
PIDFILE=/var/run/redis_${REDISPORT}.pid
#redis默认使用的核心配置文件(redis.config),如果不换核心配置不需要修改
CONF="/usr/local/redis/redis.conf"

如果redis设置了密码

在脚本中找到如下这句话
$CLIEXEC -p $REDISPORT shutdown
修改成
$CLIEXEC -a 这里写密码 -p $REDISPORT shutdown

修改执行权限

chmod 777 redis_init_script

7、配置开机启动

添加自启动脚本,在redis_init_script文件的注释下,配置前的位置上添加
注意:保留前面的“#”号

#chkonfig: 22345 10 90
#description: Start and Stop redis

保存并退出redis_init_script,配置开机启动
注意:redis_init_script文件必须存放到/etc/init.d目录下

chkconfig redis_init_script on

8、运行reids

./redis_init_script start

四、redis各数据类型的基本命令

1、通用的命令

命令注释
auth [password]登录
keys [*key*]查询key列表,查询所有的key使用 keys *
ttl [key]查看过期时间
expire [key] [time]设置过期时间
select [num]切换库,默认0-15
flushdb清空当前库
flushall清空所有库

2、String的命令

命令注释
set [key] [value]设置键值对(类似java Map的put方法)
get [key]获取键对应的值
del [key]删除键值对
setnx [key] [value]当key不存的时候,设置value
append [key] [value]将值,拼接到原本值的后面
strlen [key]查看字符串长度
incr [key]累加,自加一(纯数字字符串)
decr [key]累减,自减一(纯数字字符串)
getrange [key] [start] [end]截取值的一段内容
setrange [key] [start] [value]替换值中的一段内容
mset [key] [value] [key value …]同时设置多个键值对
mget [key] [key …]同时获取多个键值对
msetnx [key] [value] [key value …]当key不存的时候,同时设置多个value

3、hash的命令

命令注释
hset [key] [field] [value]设置hash对象
gset [key] [field]获取指定hash对象的指定属性值
hmset [key] [field] [value] [field value …]同时设置hash对象的多个属性
hmget [key] [field] [field …]同时获取hash对象的多个属性
hgetall [key]获取hash对象里面所有的属性和值
hlen [key]获取hash对象里属性的个数
hkeys [key]获取hash对象里属性名
hvak [key]获取hash对象里属性值
hexists [key] [field]判断某个属性是否存在
hdel [key] [field]删除指定属性

4、list的命令

命令注释
lpush [key] [vlaue] [value …]设置list对象,将值存到list的左边
rpush [key] [vlaue] [value …]设置list对象,将值存到list的右边
lrange [key] [start] [end]获取指定list的某个区间里面的对象
lpop [key]弹出列表最左侧的值
rpop [key]弹出列表最右侧的值
llen [key]获取list里面的元素个数
lindex [key] [index]获取list中指定下标的值
lset [key] [index] [value]修改指定下标的元素
linsert [key] [beforeafter] [value] [newVlaue]
lrem [key] [count] [value]删除几个指定值的元素

5、set的命令

命令注释
sadd [key] [vlaue] [value …]添加不重复的值
smembers [key]查看set里面的所有值
scard [key]查看set里面值的个数
sismember [key] [value]查看值是否存在
spop [key]弹出第一个元素
spop [key] [num]弹出前几个元素
srandmember [key] [count]从set里面随机获取几个对象
smove [oldkey] [newkey] [value]将oldkey里面的value元素移到newkey中
sdiff [key1] [key2]获取两set的差集,key1中有但key2中没有的
sunion [key1] [key2]获取两set的并集
sinter [key1] [key2]获取两set的交集

6、zset的命令(有序set)

命令注释
zadd [key] [score] [value] [score value …]设置member和对应的分数
zrange [key] [start] [end]查看set中的内容
zrank [key] [value]获取元素对应的下标
zscore [key] [value]获取元素对应的分数
zcard [key]统计元素个数
zcount [key] [score1] [score2]统计指定分数的个数
zrangebyscore [key] [score1] [score2]查询指定分数之间的member(包含分数1 分数2)
zrangebyscore [key] [score1] [score2] limit [start] [end]查询指定分数之间的member(包含分数1 分数2),做分页
zrem [zset] [value]删除指定元素

五、SpringBoot整合Redis

1、添加redis依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、修改配置文件

spring:
    redis:
        #使用redis的库
        database: 0
        #连接地址
        host: 127.0.0.1
        #连接端口
        post: 6379
        #密码
        password: 123456

3、编写代码

这里以一个Controller为例

@RestController
@RequestMapping("/redis")
public class RedisController{
    //注入模板
    @Autowired
    private RedisTemplate redis;
    //也可以使用StringRedisTemplate
    
    @GetMapping("/set")
    public Object set(String key,String value){
        redis.opsForValue.set(key,value);
        return "OK";
    }
    
     @GetMapping("/get")
    public String get(String key){
        return (String)redis.opsForValue.get(key);
    }
}

六、Redis进阶

1、订阅和发布

准备2个客户端,1台为发布,1台为订阅(这两个客户端要连接同一个redis)
注意:这里只是演示,实际使用的时候,我们应当选择专业的MQ

(1)进行订阅

打开一个redis客户端,用于订阅

#订阅一个叫food的频道,food只是一个标识,可以填写任意的字符串
subscribe food
#通配符订阅,这样所有的以chat为标识的消息,都会被订阅
psubscribe chat*

执行命令之后,客户端会处于一个阻塞的监听状态

(2)进行发布

打开一个redis客户端,用于发布

#向订阅了food频道的客户端发送一个汉堡
publish food burger

2、持久化

redis的数据是存在内存中的,如果突然断电我们的数据就会就是,使用持久化让数据保存在硬盘上

(1)RDB

每个一段时间,进行对redis数据进行快照,是一种全量的持久化
优势:

  • 可以灵活的配置备份的时间,每个几小时或者几天备一份一次都可以
  • 会备份成单独的一个文件,文件名称也可以进行自定义,这意味着他的还原和移动更加方便
  • 可以很容易的进行容灾,以远程的方式传输到文件服务中进行备份
  • 恢复速度相比AOF更加快速

缺点:

  • 如果在备份的过程中,出现为错误,最后一次备份的数据就会丢失
  • 在备份的时候,是通一个子进程进行备份的,在数据量较大的时候对会服务器产生压力
  • 他是一个间隔时间的备份,所以不是实施的对数据进行备份

配置RDB备份
打开核心配置文件(redis.conf),找到SNAPSHOTTING的区域

#保存规则,如果发生了一次key的变化,那么900秒之后就会备份一次
save 900 1
#如果发生了十次key的变化,那么300秒之后就会备份一次
save 300 10
#如果发生了一万次key的变化,那么60秒之后就会备份一次
save 60 10000
#默认保存的名称
dbfilename dump.rdb
#保存的位置
dir /usr/local/redis/working
(2)AOF

以日志的方式存在,地方进行写操作的时候就会触发AOF
优势:

  • 可以使得redis,更加持久健壮
  • 使用日志的形式追加,如果磁盘满了 或者其他原因出现问,可以很简单的进行修复
  • 可以进行重写,减少日志的大小
  • 包含所有的写操作,可以记录下所有的信息

缺点:

  • 日志文件相对较大
  • 在超高并发的时候会影响机器的io性能
  • AOF不会根据之前的老旧数据进行重构

配置AOF备份
打开核心配置文件(redis.conf),找到APPEND ONLY MODE的区域

#开启AOF
appendonly yes
#备份文件名称
appendfilename "appendonly.aof"
#同步策略
#一共有三种 always(每次写操作),everysec(每秒),no(关闭)
appendfsync always
#重写日志的时候是否将新的操作同步到日志中,建议用no
no-appendfsync-on-rewrite no
#重写日志的触发添加
#当文件大小超过上次文件备份之后大小的100%后,触发
auto-aof-rewrite-percentage 100
#当文件小于指定大小时,不触重写操作
auto-aof-rewrite-min-size 64mb

恢复的时候上一次误删除的数据,只需要删除AOF日志中的最后一条命令,然后重启就可以了

3、内存清理策略

  在redis中如果key设置了过期时间,并且key已经过期,此时已经无法查询value了,但是这个数据依旧会被保留在内存中,这是因为redis的内存清理策略造成的

(1)定时删除(主动)

定时随机的检查的key,如果过期则清理删除。
在redis.conf中修改

每秒随机抽取10个key进行检查
hz 10
(2)惰性删除(被动)

  当客户端请求一个已经过期的key的时候,那么redis会检查这个key是否过期,如果过期了,则删除,然后返回一个nil。这种策略对cpu比较友好,不会有太多的损耗,但是内存占用会比较高

4、内存占满的清理策略

在redis.conf中添加

#当redis的内存超过这个值的时候会真正释放掉redis中的某些键值对(单位:bytes)
maxmemory 4096
#内存满载的清理策略 默认为noeviction
maxmemory_policy noeviction
noeviction:旧缓存永不过期,新缓存设置不了,返回错误 
allkeys-lru:清除最少用的旧缓存,然后保存新的缓存(推荐使用)
allkeys-random:在所有的缓存中随机删除(不推荐)
volatile-lru:在那些设置了expire过期时间的缓存中,清除最少用的旧缓存,然后保存新的缓存 
volatile-random:在那些设置了expire过期时间的缓存中,随机删除缓存 
volatile-ttl:在那些设置了expire过期时间的缓存中,删除即将过期的

七、主从复制(读写分离)

准备3台装有redis的机器,1台作为master,2台作为slave

1、查看redis当前的状态

进入redis-cli,登录后输入

info replication

显示以下数据

#这台机器为master
role:master
#连接的从机个数
connected_slaves:0
master_replid:505dd5ab28e221e8fdff546a1ebbfb4219147693
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

2、将两台机器修改为从机

主机是不需要修改的,我们只需要核心配置文件(redis.conf)将其设置为从机并且连接到主机上就可以了

(1)打开配置文件找到REPLICATION区域
vim redis.conf
/REPLICATION
(2)配置连接的主机地址

在模块的任意位置(实际上在配置文件的任意位置上都可以),添加配置

#连接master的地址和端口 replicaof <masterip> <masterport>
replicaof 192.168.85.200 6379
# #连接master的密码 masterauth <master-password>
masterauth 123456

找下面的配置并修改

#从机的数据设置为只读
replica-read-only yes
(3)重启redis

重启之后当前的这个redis就会变成从节点连接上master,并且同步master的数据,如果master上有数据且数据量较大,可能会有点慢

(4)再次查看redis的状态

进入redis-cli,登录后输入

info replication

显示以下数据

#这里已经变从节点了
role:slave
#连接的主机地址
master_host:192.168.85.200
#连接的主机端口
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:252
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:82067392216d7336830be1a9e27ad0a6a188bb2a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:252
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:252
(5)另外一台机器也同样配置

redis的从节点不宜太多,不然可能会占用过多的网络带宽和性能
一般有三种配法
1、1主1从
2、1主2从(现在的公司一般都使用这个)
3、在1主2从的基础上给从节点再增加从节点

(6)测试

在主节点上添加数据,查看两个从节点上数据是否同步

3、无磁盘化复制(试用功能)

  在配置好从机之后,重启redis,从机会到master上复制数据文件,实际上就是master提供一个RDB给从机进行下载,是下载到在硬盘上的,如果数据量较大,且是内网环境的时候,普通的磁盘可能会限制传输速度。此时我们就需要同到无磁盘户复制,让redis将这个过程从硬盘上移到内存上

(1)打开核心配置文件修改参数
#启动无磁盘化复制
repl-diskless-sync yes
#等待时间 单位秒
repl-diskless-sync-delay 5

八、哨兵模式(sentinel)

1、什么是哨兵

  redis在主从分离的模式下,如果master发生了宕机,redis自己是不会像其他的中间件一样自动的推选出新的master的,这是就需要哨兵进程的帮助。

  哨兵(Sentinel)是用于监控Redis集群中Master状态的工具,是 Redis 高可用解决方案,哨兵可以监视一个或者多个redis master服务,以及这些master服务的所有从服务;当某个master服务宕机后,会把这个master下的某个从服务升级为master来替代已宕机的master继续工作。

2、配置哨兵

在redis的根目录下找到sentinel.conf,修改其配置
有些配置是需要自己添加或者去掉注解的

#这个配置和redis.conf是一样,绑定的ip
bind 127.0.0.1
#是否启动保护模式,如果启动了保护模式那么只有绑定的ip才能操作redis
protected-mode no
#端口号
port 26379
#是否后台运行
daemonize yes
#哨兵进程的保存文件
pidfile /var/run/redis-sentinel.pid

#哨兵的日志
logfile /usr/local/redis/sentinel/redis-sentinel.log

#工作路径
dir /tmp

#连接master的配置
#sentinel moitor <master的别名> <master的地址> <master端口> <故障转移触发的哨兵数量>
#master的别名:只能使用A-z,0-9,“.-_”这些字符
#故障转移触发的哨兵数量:例如部署了5个哨兵对这个master进行监控,当有2个哨兵发现master没有响应的时候,开始进行故障转移
sentinel monitor master-200 192.168.85.200 6479 2

#master登录密码
sentinel auth-pass master-200 123456
# master被sentinel认定为失效的间隔时间 
sentinel down-after-milliseconds master-200 30000
#剩余的slaves重新和新的master做同步的并行个数 
sentinel parallel-syncs master-200 1
# 主备切换的超时时间,哨兵要去做故障转移,这个时候哨兵也是一个进程,如果他没有去执行,超过这个时间后,会由其他的哨兵来处理 
sentinel failover-timeout master-200 180000

3、启动哨兵

之前配置了日志文件位置的话 需要创建对应的文件夹

redis-sentinel sentinel.conf

4、一些其他细节

  • 多个哨兵监控同一个主节点的时候,会自动变成集群
  • 哨兵节点至少3个或者奇数个,故障转移触发的哨兵数量一定是一半+1个,这样避免哨兵的主观判断
  • 哨兵最好分布在不同的服务器节点上
  • 一组哨兵最好只监听一组主从
  • 当主节点宕机后,哨兵会在从节点中推选一个做为主节点
  • 当之前的主节点重新上线后,会以从节点的身份加入集群

5、原Master恢复后不同步问题

  如果你仔细的操作个上面的配置,会发现原来的Master恢复成Slave后,状态为master_link_status:down,实际上是因为我们没有配置它的masterauth属性,所以只需要修改redis.conf中的masterauth为对应的密码即可,这里为123456。

(1)一般master数据无法同步给slave的方案检查为如下:
  • 网络通信问题,要保证互相ping通,内网互通。
  • 关闭防火墙,对应的端口开发(虚拟机中建议永久关闭防火墙,云服务器的话需要保证内网互通)。
  • 统一所有的密码,不要漏了某个节点没有设置。

6、哨兵信息检查

在redis-cli中可以使用命令让哨兵查看各节点的信息

# 查看master节点信息 
sentinel master <masterName> 
# 查看slaves节点信息 
sentinel slaves <masterName> 
# 查看哨兵节点信息 
sentinel sentinels <masterName> 

7、SpringBoot整合哨兵

(1)配置SpringBoot

原先spring整合单机单节的配置

spring:
    redis:
        database: 1
        host: 192.168.85.200
        port: 6379
        password: 123456

将配置修改成哨兵的模式

spring:
    redis:
        database: 1
        password: 123456
        sentinel:
            #master的别名
            master: master-200
            #所有的哨兵节点
            nodes: 192.158.85.200:26379,192.158.85.201:26379,192.158.85.202:26379
(2)为什么需要通过哨兵模式进行连接
  • 当主节点宕机之后,如果使用原先的单节点连接的方法,就无法在使用redis
  • 原先的配置并没有做到读写分离,还是单节的读写,从节点压根没有使用上

8、哨兵模式的缺点

  在主从复制的基础上,哨兵引入了主节点的自动故障转移,进一步提高了Redis的高可用性;但是哨兵的缺陷同样很明显:哨兵无法对从节点进行自动故障转移,在读写分离场景下,从节点故障会导致读服务不可用,需要我们对从节点做额外的监控、切换操作。
  此外,哨兵仍然没有解决写操作无法负载均衡、及存储能力受到单机限制的问题;这些问题的解决需要使用集群。

九、Redis集群

1、Redis-Cluster 集群

  主从复制以及哨兵,他们可以提高读的并发,但是单个master容量有限,数据达到一定程度会有瓶颈,这个时候可以通过水平扩展为多master-slave成为集群。支持海量数据,实现高可用与高并发。哨兵模式其实也是一种集群,他能够提高读请求的并发,但是容错方面可能会有一些问题,比如master同步数据给slave的时候,这其实是异步复制,这个时候master挂了,那么slave上的数据就没有master新,数据同步需要时间的,1-2秒的数据会丢失。master恢复并转换成slave后,新数据则丢失。

特点
  • 每个节点知道彼此之间的关系,也会知道自己的角色,当然他们也会知道自己存在与一个集群环境中,他们彼此之间可以交互和通信,比如ping pong。那么这些关系都会保存到某个配置文件中,每个节点都有,这个我们在搭建的时候会做配置的。
  • 客户端要和集群建立连接的话,只需要和其中一个建立关系就行。
  • 某个节点挂了,也是通过超过半数的节点来进行的检测,客观下线后主从切换,和我们之前在哨兵模式中提到的是一个道理。
  • Redis中存在很多的插槽,又可以称之为槽节点,用于存储数据
集群容错

  构建Redis集群,需要至少3个节点作为master,以此组成一个高可用的集群,此外每个master都需要配备一个slave,所以整个集群需要6个节点,这也是最经典的Redis集群,也可以称之为三主三从,容错性更佳。所以在搭建的时候需要有6台虚拟机。请各自准备6台虚拟机,可以通过克隆去构建,使用单实例的Redis 去克隆即可,如果之前配置了主从或是哨兵建议删除 。
在这里插入图片描述

2、配置三主三从集群

这里演示是新版本的集群搭建,老版本需要使用redis-trib.rb这里不做演示,使用机器的配置如下

主从一主从二主从三
主节点192.168.85.200192.168.85.201192.168.85.202
从节点192.168.85.203192.168.85.204192.168.85.205
(1)修改集群配置文件(这里的配置是所有的节点都要设置的)

配置前保证redis是关闭的
在redis的核心配置文件(redis.conf)里面找到REDIS CLUSTER区域

#启动Redis-Cluster 集群
cluster-enabled yes

#每个节点的配置文件
#这里保存着对应节点的配置信息,和其他节点的对应关系
#这是redis自己进行管理的,不需要我们进行干预,只需要打开原本的注释就行了
cluster-config-file nodes-6379.conf

#节点超时的时间 (单位:秒)
cluster-node-timeout 5000

#开启AOF持久化模式
appendonly yes

如果配置出现问题,可以删除掉原先的AOF持久化文件,但是要注意文件删除,持久化的数据也就消失了

(2)使用redis-cli配置集群

进入redis目录里的src文件夹
每一个节点之间使用空格分开

redis-cli -a 密码 --cluster create 192.168.85.200:6379 192.168.85.201:6379 192.168.85.202:6379 192.168.85.203:6379 192.168.85.204:6379 192.168.85.205:6379 --cluster-replicas 1

执行后,会打印出集群配置信息,如果没有问题就输入yes,回车

(3)检测集群信息
redis-cli --cluster check 192.168.85..200:6380
(4)连接集群中的某个节点
redis-cli -c -a 密码 -h 节点ip -p 节点端口

#连接后,查看当前节点信息
cluster info
#查看所有节点信息
cluster nodes

3、slots槽节点

当我们查询集群信息的时候,可以看到这么一段话

[OK] All 16384 slots covered

这里的意思就是 一共有16384个槽节点,那么什么是槽节点

(1)slot是怎么分配的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hOQnhwV1-1577677344717)(en-resource://database/2525:1)]
这里可以看到3个master是平分了所有槽节点,而从节点是没有槽节点的

(2)slot是怎么存储数据的

  当来了一条数据,redis就会对数据的key进行计算 "hash(key)%槽数量 "这样就可以算出一个对应的slot,经过计算所有值相同的数据都会被完整的保存在这个slot中。如果在200的机器上查询keys * 是查看不到其他slot里的数据,但是get [key]是会自动切换节点查询到的
  当然存入主节点的时候,同时会复制一份到对应的从节点上,当主节点宕机后,从节点就会接替主节点的位置。

4、SpringBoot整合Redis-Cluster集群

spring:
    redis:
        password: 123456
        cluster:
            #所有的节点,nodes后面是不换行的,页面上显示的有问题
            nodes: 192.158.85.200:6379,192.158.85.201:6379,192.158.85.202:6379,192.158.85.203:6379,192.158.85.204:6379,192.158.85.205:6379

十、Redis缓存穿透与雪崩

1、缓存穿透的解决方案

(1)什么是缓存穿透

  缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。

(2)缓存穿透解决方案

缓存空对象. 将 null 变成一个值.
  可以采用一个简单粗暴的方法,如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
缓存空对象会有两个问题:
  第一,空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间 ( 如果是攻击,问题更严重 ),比较有效的方法是针对这类数据设置一个较短的过期时间,让其自动剔除。
  第二,缓存层和存储层的数据会有一段时间窗口的不一致,可能会对业务有一定影响。例如过期时间设置为5分钟,如果此时存储层添加了这个数据,那此段时间就会出现缓存层和存储层数据的不一致,此时可以利用消息系统或者其他方式清除掉缓存层中的空对象。

布隆过滤
  对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃。还有最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
布隆过滤器的问题:

  • 当数据从数据库和redis中删除的时候,无法从布隆过滤器中无法删除的
  • 误判率,由于布隆过滤器的本身的运行机制,会导致,对于某些key 在默写情况下出现误判,把一个不存在的值,判断成存在

2、布隆过滤器

  布隆过滤器的原理是,当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。

  bloom filter之所以能做到在时间和空间上的效率比较高,是因为牺牲了判断的准确率、删除的便利性

  • 存在误判,可能要查到的元素并没有在容器中,但是hash之后得到的k个位置上值都是1。如果bloom filter中存储的是黑名单,那么可以通过建立一个白名单来存储可能会误判的元素。
  • 删除困难。一个放入容器的元素映射到bit数组的k个位置上是1,删除的时候不能简单的直接置为0,可能会影响其他元素的判断。可以采用Counting Bloom Filter

3、缓存雪崩与预防

(1)什么是缓存雪崩

缓存击穿
  缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力
缓存雪崩
  缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库

(2)解决方案

缓存击穿

  • 设置热点数据永远不过期
  • 加互斥锁

缓存雪崩

  • 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  • 如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
  • 设置热点数据永远不过期。
  • 多缓存结合(使用Redis做分布式缓存,memcache做单节点缓存)
  • 使用第三方Redis 例如:阿里云和腾讯云

十一、批量查询优化

1、MultiGet(速度快,开销小)

对于需要一次性获取多个key的value时,例如下面代码

public Object getAlot(String... keys){
    List<String> resutl = new ArrayList<>();
    for(String k:keys){
        resutl.add(redisOperator.get(k));
    }
    return resutl;
}

修改成使用MultiGet,对应的就是mget命令

public Object getAlot(String... keys){
    List<String> keysList = Arrays.asList(keys);
    return redisTemplate.opsForValue().multGet(keys);
}

2、pipeline(更加灵活)

每次对redis发起请求,都需要创建相互的链接,这样就有额外的开销,使用pipeline建立管道,进行优化

public List<Object> getAlot(String... keys){
     List<Object> resutl = redisTemplate.executePipelined(new RedisCallback<String>() {
        @Override
        public String doInRedis(RedisConnection connection) throws DataAccess{
            StringRedisConnection src = (StringRedisConnection)connection;
            for(String k:keys){
                src.get(k);
            }
            return null;
        }
    });
    return resutl;
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Redis集群中,三主三从架构是一种常见的搭建方式。每个节点都可以相互连通,客户端可以连接任何一个节点来访问整个集群中的数据和执行操作。三个主节点提供服务,而三个从节点则提供备份功能,存储集群中所有主节点和从节点的信息。 在搭建这种集群时,不需要修改端口配置,因为每个节点都在不同的机器上,这样才能实现真正的高可用性。如果在同一台机器上搭建集群,那就是伪集群了。 使用哨兵模式搭建三主三从的Redis集群有一些优点和缺点。优点包括:主从节点的自动切换使得系统更加健壮,可用性更高。缺点则在于Redis较难支持在线扩容,特别是在集群容量达到上限时,进行在线扩容会变得非常复杂。这时候,集群模式可能是一个更好的选择。 综上所述,使用三主三从架构搭建Redis集群可以提供高可用性和数据备份功能,但在线扩容可能存在一定的挑战。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Redis三主三集群搭建(三台机器)](https://blog.csdn.net/weixin_44519124/article/details/113274037)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Redis搭建集群三主三集群模式](https://blog.csdn.net/xiefazhi123/article/details/119147657)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值