技术复盘(1)--redis

技术复盘(1)–redis

会针对redis在linux和windows上的使用进行阐述,主要以centos7为主
【如果redis部署在服务器上,一定一定要设置密码,否则服务器容易被当矿机】

资料地址

redis官网:https://redis.io/
redis中文网:https://www.redis.net.cn/
狂神说redis视频教程地址:https://www.bilibili.com/video/BV1S54y1R7SB

准备工作

必备:
主机:windows 或 centos7
redis:Redis-x64-3.2.100.zip 或 redis-5.0.7.tar.gz
jdk:1.8

选备:
xshell:远程连接linux服务器
xftp:传输文件到远程服务器
这两者有很多替代品,大家使用的可能都不一样,只要能达到对应的效果就行。

相关资料自取:
jdk链接:https://pan.baidu.com/s/1jp89Aq1jcX0kfezKis-ktw?pwd=iuml
提取码:iuml
redis链接:https://pan.baidu.com/s/1yc6jC5Sy-PkxavawVa6XxQ?pwd=ukg0
提取码:ukg0

发展史

  长话短说,这也不是重点,为了解决数据读取慢而诞生的。
  为什么数据读取会慢?在myslq中数据读取时,会对磁盘进行操作,虽然mysql底层采用的b+树,上千万的数据通常也只需要读取磁盘4次就能拿到数据,但在面对高并发的情况下,无疑会降低效率。读取速度通常cpu>内存>磁盘,cpu资源太过宝贵,磁盘性能又太低,于是乎将数据存入内存便成为了一种解决方案,redis因此诞生。
redis将数据存入内存,采用单线程方式运行,它的运行效率不依靠cpu,而是内存容量和网络带宽。

redis-windows

  将资料里的jdk-8u172-windows-x64.exe和Redis-x64-3.2.100.zip下载下来,jdk1.8双击运行一直点点点就能安装成功,Redis-x64-3.2.100.zip解压后进入目录,在该目录下打开cmd窗口,输入 redis-server.exe redis.windows.conf 即可运行。

redis-windows-说明

  redis官方并不太支持使用windows运行redis,Redis-x64-3.2.100.zip是由微软进行维护,但目前已停止维护。截止于2023年4月8日redis官网已更新到 7.0.10版本,但在windows上依旧只能运行最高Redis-x64-3.2.100版本。所以本文也主要针对linux系统对redis5.0版本进行阐述。

redis-centos7

  在centos7上操作redis步骤:安装jdk1.8->安装redis->配置redis->操作redis。
单纯使用redis不需要安装jdk,redis是采用的c语言进行开发,但跑的程序通常是java,所以这里先安装下jdk。

安装jdk

  步骤1-解压jdk:进入/usr/local目录下,新建java文件夹,进入java文件夹,使用xftp或相似工具上传jdk1.8的包,使用ll查看是否上传成功,使用tar -zxvf jdk-8u162-linux-x64.tar.gz解压jdk。解压时会输出一大串日志,日志就不截图了。
步骤1截图
  步骤2-jdk环境配置:输入 vim /etc/profile 进入系统配置文件,在配置文件最底部输入以下数据,然后退出。退出后输入 source /etc/profile 重启配置文件,重启后输入java -version查看是否安装成功。

export JAVA_HOME=/usr/local/java/jdk1.8.0_162
export CLASSPATH=$JAVA_HOME/lib
export PATH=$PATH:$JAVA_HOME/bin

  扩展:网上有些教程修改的配置文件是 /.bashrc,与 /etc/profile 相比的区别在于: /.bashrc中的配置文件只对当前用户生效,而 /etc/profile 是系统配置文件,对所有用户生效。

安装redis

  步骤1-解压redis:使用xftp或类似工具上传redis-5.0.7.tar.gz到/opt目录,然后使用tar -zxvf redis-5.0.7.tar.gz 解压得到redis-5.0.7文件夹。
  步骤2-安装一些redis必备的:先进入redis解压目录,再进行操作,操作和截图如下,截图中输出信息代表安装成功,第一次安装很慢并会输出很多日志:

1.安装c++
yum install gcc-c++
2.环境安装
make
3.查看
make install

在这里插入图片描述
  步骤3-配置redis:进入/usr/local/bin目录下,会发现里面有很多和redis相关的服务,在该目录下使用make redisConfig建立redisConfig目录,如图所示。
在这里插入图片描述
  进入redisConfig目录,使用cp /opt/redis-5.0.7/redis.conf ./将redis.conf文件复制过来;输入vim redis.conf进入复制过来的配置文件,将daemonize改为yes。退出文件。
在这里插入图片描述
  步骤4-启动redis:回到/usr/local/bin目录,输入 redis-server redisConfig/redis.conf 启动redis服务器,输入redis-cli启动redis客户端,输入exit退出redis客户端。至此redis从安装到启动成功结束。

redis安装总结:
1.新建redisConfig目录存放redis.conf配置文件的意义
因为我们需要对配置文件进行修改,但在源文件上修改万一改错了就非常麻烦,所需拷贝一个redis.conf到redisConfig下专门拿来给我们修改,改错了大不了再拷贝一个过来。
2.修改daemonize为yes的意义
daemon翻译为中文叫守护进程,daemonize翻译为中文叫后台运行,避免每次启动服务器都需要重新启动redis。

redis-key基本命令

首先redis-cli进入客户端,命令和操作如下:
redis所有命令:https://www.redis.net.cn/order/

1.设置name的值为abaaba
set name abaaba
2.覆盖name的值为zhangsan
set name zhangsan
3.获取name的值
get name
4.获取所有的key的值
keys *
5.设置name的过期时间为10秒
expire name 10
6.查看name还有好久过期,为负数代表已过去
ttl name
7.清空当前redis库
flushdb
8.清空redis的所有库【redis一共有16个库】
flushall
9.查看name的类型【name过期了,这儿我重新设置了个name,然后查看其类型】
type name

在这里插入图片描述

redis-string命令

首先redis-cli进入客户端,命令和操作如下:
redis所有命令:https://www.redis.net.cn/order/

1.设置stu的值为xuesheng
set stu xuesheng
2.向stu追加-zhangsan,返回值为stu的总长度
append stu "-zhangsan"
3.获取stu的总长度
strlen stu
4.设置view的值为0【模拟信息热度】
set views 0
5.views自增1【热度+1】
incr viewss
6.viess自减1
decr views
7.views自增10【热度+10】
incrby views 10
8.views自减10
decrby views 10
9.【redis-string中还包括对字符串的截取、替换等操作,与对java中的string的操作同理】

在这里插入图片描述

【redis-string重要命令】
1.设置mykey1的值为key1,过期时间为10秒
setex mykey1 key1 10
2.设置mykey2的值为key2,且只有当mykey2不存在时才设置
setnx mykey2 key2
3.批量设置k1 k2的值为v1 v2
mset k1 v1 k2 v2
4.批量获取k1 k2的值
mget k1 k2
5.批量设置k3 k4的值为v3 v4,且只有当k3和k4不存在时才设置
msetnx k3 v3 k4 v4
【明明很简单,为什么说很重要?因为这些命令保证的是数据一致性,事务原子性,在分布式中解决高并发问题,锁续命,就需要用到这些】

在这里插入图片描述

redis-list命令

首先redis-cli进入客户端,命令和操作如下:
redis所有命令:https://www.redis.net.cn/order/
list的大部分命令都是加个l。
list可以看作一个双端队列,默认情况下左进左出,先进后出

1.情况当前redis库,防止之前的数据干扰
flushdb
2.向list1中加入k1 k2 k3 k4
lpush list k1
3.查看list1中的个数
llen list1
4.查看list1中的所有数据【最后一个加入的数在最前面,验证了先进后出】
lrange list1 0 -1
5.从list1的右边加入k5【最后一个加入的数在最后面,验证了是一个双端队列】
rpush list1 k5
6.查询list1中指定索引为0的值
lindex list1 0
9.弹出list1中的第一个数
lpop list1
【还包含截取、弹出添加组合命令等,这里不再继续演示,需要用的时候查官网即可】

在这里插入图片描述

redis-set命令

首先redis-cli进入客户端,命令和操作如下:
redis所有命令:https://www.redis.net.cn/order/
set特点:值不能重复
set的大部分命令都是加个s。

1.先清空数据,防止有干扰
flushdb
2.向set1中添加setvalue1数据
sadd set1 setvalue1
3.查看set1中的所有数据
smember set1
4.判断set1中是否含有setvalue1数据
sismember set1 setvalue1
5.移除set1中的setvalue1数据
srem set1 setvalue1
6.向set1中添加value1 value2 value3数据
sadd set1 value1 value2 value3
7.从set1中【随机】取一个值,是取不是取出!
srandmember set1 1
8.从set1中【随机】弹出一个值,与list中的lpop不同,set中是随机弹出。
spop set1 1

在这里插入图片描述

【set做差集 并集 交集】
1.建立set2 set3 set4,并输入不同的数据
sadd set2 a b c
2.查看set2中有的,但set3中没有的【差集】
sdiff set2 set3
3.查看set2中有的,但set3和set4中没有的【差集】
sdiff set2 set3 set4
4.查询set2和set3中都有的【交集】
sinter set2 set3
5.查询set2和set3中加起来的,set集合自动去重【并集】
sunion set2 set3

在这里插入图片描述

redis-hash命令

首先redis-cli进入客户端,命令和操作如下:
redis所有命令:https://www.redis.net.cn/order/
hash特点:存储的是键值对
hash的大部分命令都是加个h。

1.先清理当前数据库,防止数据干扰
flushdb
2.向hash1中添加数据,key为k1,value为v1
hset hash1 k1 v1
3.向hash1中批量添加数据
hmset hash1 k2 v2 k3 v3
4.从hash1中批量获得数据
hmget hash1 k1 k2
5.获取hash1中的所有数据
hgetall hash1
6.删除hash1中的key为k1的数据,删除key同时也会删除对应的value
hdel hash k1
7.获取hash1的长度
hlen hash1 
8.获取hash1中的所有key
hkeys hash1
9.获取hash1中的所有value
hvals hash1

在这里插入图片描述

redis-zset命令

首先redis-cli进入客户端,命令和操作如下:
redis所有命令:https://www.redis.net.cn/order/
zset特点:值不能重复,并且有序,有序是根据权重来实现
zset的大部分命令都是加个z。

1.先清空,防止数据干扰
flushdb
2.添加3条数据,数据权重分别为1000 3000 2500
zadd salary 1000 zhangsan 3000 lisi 2500 wangmazi
3.查询salary数据,区间范围为负无穷到正无穷
zrangebyscore salary -inf +inf
3.查询salary数据,区间范围为负无穷到正无穷,并输出权重
zrangebyscore salary -inf +inf withscores
4.查询salary数据条数
zcard salary
5.查询salary所有数据【正序】
zrange salary 0 -1
6.查询salary所有数据【逆序】
zrevrange salary 0 -1
7.移除salary中的zhangsan数据
zrem salary zhangsan

在这里插入图片描述

redis-geospatial命令

首先redis-cli进入客户端,命令和操作如下:
redis所有命令:https://www.redis.net.cn/order/
geospatial特点:地图定位,通过经纬度判断直线距离,判断用户之间的直线距离。
geospatial的大部分命令都是加个geo。

1.先清空,防止数据干扰
flushdb
2.添加重庆和北京两个城市的经纬度
geoadd china:city 106.504962 29.533155 chongqing 116.405285 39.904989 beijing
3.获取重庆的经纬度
geopos china:city chongqing
4.判断重庆和北京的直线距离【米】
geodist china:city chongqing beijing
5.判断重庆和北京的直线距离【千米】
geodist china:city chongqing beijing km
6.以经度为110 维度为30为中心,附近1000km内的城市【经纬度相差差一点点,实际距离就会相差很大,所以我这里有好几次都没得到结果】
georadius china:city 110 30 1000 km
7.以经度为110 维度为30为中心,附近1000km内的城市,并显示相差距离
georadius china:city 110 30 1000 km withdist
8.以北京为中心,显示附近1500km的所有
georadiusbymember china:city beijing 1500 km

在这里插入图片描述

redis-hyperloglog命令

首先redis-cli进入客户端,命令和操作如下:
redis所有命令:https://www.redis.net.cn/order/
hyperloglog特点:Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。简而言之就是节约内存,方便计数,但有误差
hyperloglog的大部分命令都是加个pf。

1.先清空,防止数据干扰
flushdb
2.向key中添加a b ....i
pfadd key a b c d e f g h i
3.计算key的数量
pfcount key
4.向key1中添加 j k l m n
pfadd key1 j k l m n
5.将key和key1的数据合并到key2【并集】
pfmerge key2 key key1
6,计算key2的数据量

在这里插入图片描述

redis-bitmaps命令

首先redis-cli进入客户端,命令和操作如下:
redis所有命令:https://www.redis.net.cn/order/
bitmaps特点:位存储 0和1。应用于只有两个状态的场景:打卡未打开、登录未登录、活跃未活跃…
bitmaps的大部分命令都是加个bit。

1.清空库,防止数据干扰
flushdb
2.设置一个sign存储从2023年4月1日到2023年4月5日的签到情况,0代表未签到,1代表签到
setbit sign 20230401 0
3.获取2023年4月1日的是否打卡
getbit sign 20230401
4.获取sign中的打卡天数
bitcount sign

在这里插入图片描述

redis事务

重点:redis具有事务,但事务不保证其原子性!!!
redis事务异常有两种:【后面有例子,结合看】
1.运行时异常(命令编辑没错,但运行有错,只有有错的一行不生效)
2.编辑时异常(命令本身就有错,全部不生效)
编辑时异常感觉上是保证了原子性,但运行时异常并没有保证原子性,所以得出redis虽然具有事务,但事务不保证其原子性。
redis事务流程:开启事务->入队->执行/取消

1.先清空,防止数据干扰
flushdb
2.开始事务
multi
3.设置值加入队列
set key1 v1
4.启动事务,如果取消事务就是discard
exec
5.查询key1 key2的值【都能查询出来,说明事务生效】
mget key1 key2
----------开始验证redis中事务不具备原子性(运行异常)----------
6.开启事务
multi
7.设置值加入队列
set key3 v3
8.设置list队列的0号位数据为1【因为并没有list集合,且采用的lset命令,
在运行时必定会有异常,如果该行的上下行都执行成功,则可说明事务并没有
回滚,并没有保证数据一致性,从而验证事务不具备原子性】
lset list 0 1
9.设置值加入队列
set key4 v4
10.执行事务【lset list 0 1报错!】
exec
11.获取key3 和 key4的值,获取成功,但获取list时并没有数据,说明运行时报错
并没有触发事务回滚,验证redis事务不具备原子性完成。

在这里插入图片描述

----------开始验证redis中事务不具备原子性(编辑异常)----------
1.先清空库,防止数据干扰
flushdb
2.开启事务
multi
3.设置key1的值,该命令正常
set key1 v1
4.随便输入条命令,触发编辑时异常,但可以发现事务并没有停止
asdfg
5.设置key2的值,该命令正常
set key2 v2
6.执行
exec
7.查询key1 key2的值,发现并没有,从而验证编辑时异常(命令本身就有错,全部不生效)
mget key1 key2

在这里插入图片描述
锁:
redis悲观锁:认为任何时候都会出问题,永远加锁,会严重影响性能
redis乐观锁:认为任何时候都不会出现问题,不会上锁,但更新数据时会去检查一下数据是否被修改过,如果修改过就不会执行成功。对应redis中的加锁命令为 watch,解锁命令为 unwatch

springboot集成jedis

1.查询redis会发现它目前是只能本机连接=>redis-server 127.0.0.1:6379
在这里插入图片描述
2.进入到redisConfig目录下的redis.conf,注释掉bind 127.0.0.1,修改protocted-mode为no,保存退出,重启redis服务
在这里插入图片描述
3.重启redis服务器后再次查询redis进程,发现已变成redis-server *:6379,表示允许其他主机连接
在这里插入图片描述
(一 jedis操作redis)1.创建springboot项目,在pom文件中放入两个依赖,fashjson是为了方便字符串和json之间转换,没这需求可以不导,如下:

        <!--jedis-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
        </dependency>

        <!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>

在这里插入图片描述
(一 jedis操作redis)2.测试是否能够连接成功,输出为PONG代表连接成功。在redis中如何操作的,现在在jedis中就是如何操作,两者用的命令基本一样。

Jedis jedis = new Jedis("xxx.xxx.xxx.xxx",6379);
System.out.println(jedis.ping());

在这里插入图片描述
(二springboot整合redis)1.替换原本的依赖

        <!--整合redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- fasterxml -->
        <dependency>
            <groupId>org.kie.modules</groupId>
            <artifactId>com-fasterxml-jackson</artifactId>
            <version>6.3.0.CR1</version>
            <type>pom</type>
        </dependency>
        <!-- commons-pool2 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

在这里插入图片描述

(二springboot整合redis)2.配置redis,这里我一开始远程的服务器的redis,用jedis的时候一切正常,用lettuce一直失败,最终屈服了,改成连接本地的,就正常了。
在这里插入图片描述

(二springboot整合redis)3.自定义redis配置文件,主要是配置序列化

package com.example.redisjedis.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }


}

在这里插入图片描述
(二springboot整合redis)4.操作redis,先注入redistemplate,然后通过redistemplate的方法直接调用即可,具体如下图。ops全称为:Operations(操作),opsfor代表操作什么什么,
在这里插入图片描述

总结:(一 jedis操作redis)的区别(二springboot整合redis):jedis操作redis底层肯定是用的jedis,这个是没疑惑的,但是springboot整合redis的底层是用的Lettuce操作redis,并且在springboot整合redis中,可以说是已经不再支持jedis了。如果你希望使用jedis操作redis,请用第一种配置方式。
关于jedis和Lettuce的差别,我在网上搜了几点供参考:如果大家有更能通俗易懂的话语来描述,可以在下方留言,我看见了会加入文中。

  1. 性能:Lettuce相比Jedis在性能上有一定的优势,因为Lettuce使用了Netty作为底层网络通信框架,而Netty采用了NIO模型,有更好的IO性能和更低的资源消耗。

  2. 线程安全:Lettuce相比Jedis在线程安全方面有一定优势,因为Lettuce的线程模型是基于Netty的EventLoop线程模型,EventLoop是线程安全的,可以进行全局共享,而Jedis则不是线程安全的,不支持多线程操作Redis。

  3. 高可用性:Lettuce支持Redis Sentinel和Redis Cluster,可以实现自动的Master切换和节点故障恢复,而Jedis则不支持。

  4. API设计:Jedis的API设计更加简单易用,与Redis命令一一对应,易于学习和使用。而Lettuce的API设计更加面向对象,提供了更加灵活和易于扩展的接口,支持异步操作和响应式编程。

  5. 内存占用:Lettuce相比Jedis占用更多的内存,因为Lettuce使用了Netty作为底层网络通信框架,而Netty本身就占用了较多的内存资源。

总之,Lettuce相比Jedis在性能、线程安全和高可用性方面有优势,而Jedis则更加简单易用,两者各有优缺点,可以根据具体的业务需求选择适合的客户端库。

持久化存储

默认情况下采用rdb持久化存储,aof默认不开启。

RDB

功能:每隔一段时间,开辟一个子线程来保存数据,父线程无需保存数据,保证了redis性能,但如果redis宕机了,会无法保存最后一段时间的数据,默认保存名为dump.rdb。
触发机制:达到默认的save条件,触发shutdown命令,触发flushall命令
读取dump.rdb文件:dump.rdb文件和redis-server在同一级目录下,每次启动redis时会自动读取dump.rdb
优点:开辟子线程备份提高效率,
缺点:子线程会占用一定的内存空间,如果宕机会丢失最后一段时间的数据

AOF

功能:将写的操作备份,只会在文件中追加操作,默认一秒备份一次,宕机会丢失最后一秒的数据,默认不开启,需要在配置文件中将appendonly的no改为yes,默认保存名为appendonly.aof。
优点:虽然默认是一秒备份一次,但可以修改配置文件为每一次都备份,会增加性能消耗
缺点:aof文件远远大于rdb,因为aof备份每一次都是追加写的操作,如果追加后文件的大小超过了预期(默认64mb),会触发重写操作。

关于aof的重写操作我找了点资料:

  在 AOF 重写过程中,Redis 是将新的 AOF 文件和旧的 AOF 文件混合在一起进行持久化的。重写操作从当前内存状态开始,按照写命令的顺序重新构建了一个新的 AOF 文件。因为这个新的 AOF 文件包含了从 Redis 启动到开始 AOF 重写之间的所有操作。

  具体来说,Redis 具体是这样操作的:Redis 将 AOF 缓冲区中的写命令同时写入新的 AOF 文件和旧的 AOF 文件中,这个过程称作 AOF 重写的预写模式。等到 AOF 缓冲区中的所有写命令都被处理完后,Redis 会停止在旧的 AOF 文件中追加写入,并关闭旧的 AOF 文件,将新的 AOF 文件重命名(原子操作)以替代旧的 AOF 文件。

  这样,Redis 就可以避免在旧的 AOF 文件上进行读取和写入操作,而无需为重写创建一个临时文件(备份文件)。因此,AOF 重写过程中只保留一个 AOF 文件,这个文件包含了从Redis 启动到开始 AOF 重写之间的所有操作,而没有丢失任何数据。

订阅发布

  订阅发布只是说redis也可以做,但专业的还得是mq。
在这里插入图片描述

伪主从复制-临时

  概念:主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制是单向的,只能由主节点到从节点,且该操作是默认进行的。Master以写为主,Slave只能读不能写
  因为系统大部分进行的都是读的操作,所以通常是一主多从。
  复制原理:Slave启动成功连接到master后会发送一个sync同步命令,Master接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,并完成一次完全同步。
    全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
    增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步但是只要是重新连接master,一次完全同步(全量复制)将被自动执行

  一个主节点可以有多个从节点,但一个从节点只能有一个主节点,redis默认都是主节点。可通过info replication查看当前redis的属性。
在这里插入图片描述
开始搭建伪redis集群,在一台电脑上启动三台redis,端口分别为87 88 89,将87作为主机,88和89作为从机。
步骤1:将redis.config复制三份并重命名,如图:
在这里插入图片描述
步骤2:修改4个东西:端口、pidfile、logfile、dbfilename,如下图所示,三个都要修改
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
步骤3:配置完后启动这三个redis,下图表示启动成功,目前三台都是主机。
在这里插入图片描述
步骤4:配置从机,进入88和89,输入slaveof 127.0.0.1 87表示认当前主机下的87端口为主机,再输入info replication可查看到当前redis已经成为从机。
在这里插入图片描述
注:该操作是临时的,如果从节点重启,又会变成主节点,需要再次手动配置!如果要达到永久的效果,可通过修改配置文件实现。如果主节点宕机,就需要手动再选择一个主节点。

哨兵模式

特点:主节点宕机后,自动选取从节点成为主节点,原本的主节点即使重新连接回来,也会被当做一个从节点,哨兵模式是主从复制的进阶。
精简流程:建立一个独立的哨兵进程监控所有的主从节点,如果主节点宕机,就从从节点中选取一个作为主节点。
详细流程:假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。
缺点:配置麻烦,哨兵也有可能宕机的风险,通常也要配置一个哨兵的集群,哨兵模式起步1主2从3哨兵,如下图所示:
在这里插入图片描述
(配置哨兵)1.在和redis.conf相同的目录处,我的是/usr/local/bin/redisConfig/,配置sentinel.conf【前提是已经完成了1主2从并启动】

在这里插入图片描述
sentinel.conf配置文件中的内容如下:

# <master-name> 主节点名字,只能有A-Z 0-9 ._-组成
# ip port 地址和端口
# <quorum> 至少有多少个哨兵认为该节点不可用,才算真的不可用
# sentinel monitor <master-name> <ip> <port> <quorum>
sentinel monitor mymaster 127.0.0.1 87 1

# 如果redis有密码则配置
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster xxx

# 如果主节点在多少毫秒内未响应,则主管认为主节点下线,默认30秒
# <milliseconds> 多少毫秒
# setntinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000

# 这个先不忙配,我配置了无法启动哨兵
# 主节点崩了 通知script-path下,默认script-path为/var/redis/reconfig.sh
# sentinel client-reconfig-script <master-name> <script-path>
# sentinel client-reconfig-script mymaster /usr/local/bin/redisConfig/sentinelReconfig.sh
~                                                                                         

我的配置截图:
在这里插入图片描述

(配置哨兵)2.启动哨兵,我服务器很撇,哨兵起多了会直接宕机,这里就起一个。
在这里插入图片描述

缓存穿透、缓存击穿和雪崩

缓存穿透概念:用户想要查询一个数据,发现redis内存数据库没有,于是向持久层数据库查询,发现持久层数据库也没有,于是本次查询失败。当大量用户执行此操作(恶意攻击),对持久层数据库发送了大量的请求,这时候就相当于出现了缓存穿透。
解决方案:
1.布隆过滤器,这儿我还没看太懂,先放一张图
在这里插入图片描述
2.存放空对象,如果持久层数据库中也查询不到数据,就放一个空对象在redis中,下次相同的请求到来时,能够直接在redis中拿到空对象返回结果,就不会访问持久层数据库。
缺点:治标不治本,把持久层数据库的压力给到了redis

在这里插入图片描述
缓存击穿概念:是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞,当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。
解决方案:

  1. 预先加载:在缓存失效的时候,立即发起一个异步的线程去更新缓存,避免缓存失效后访问量大的情况下直接打到数据库。

  2. 采用热点数据永不过期的策略:对于一些非常热点的数据,可以将其过期时间调整为永不过期,后续更新数据时再手动更新缓存。

  3. 增加降级处理:如果缓存失效导致数据库出现过大压力,可以采用降级的策略,暂时关闭一些服务来减轻数据库的压力,避免整个系统崩溃。

  4. 使用分布式缓存:将一个key存储在多个缓存服务器上,防止某个缓存服务器宕机而导致缓存击穿的情况发生。

雪崩:redis集体失效,比如redis集群在同一个地方,这地方突然停电了,就会造成redis集体失效,这时请求会全部冲向持久层数据库,造成持久层数据库挂掉。
解决方案:异地多活,把redis服务放在不同的地方。

缓存击穿和缓存穿透的区别:缓存击穿是查得太多了,缓存穿透主要是查不到。

缓存击穿、缓存穿透、雪崩的共同点:都是大量请求访问持久层数据库,持久层数据库扛不住。如果请求量小,这些问题都不会出现。

结束语:

本文在后续如果作者遇到了关于redis的问题也会持续更新,针对本文中的不足有兴趣的小伙伴可以在下方留言,我看见了会不断改进。最后祝每一位砥砺前行的小伙伴最终都能如愿以偿。

本人复习阶段视频源自于狂神说,该up主b站视频教程地址为:https://www.bilibili.com/video/BV1S54y1R7SB

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jianjian??

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值