什么是Redis?

什么是Redis?

1、NOSQL

​ 介绍Redis前讲讲什么是nosql,nosql与我们sql是两个不同的东西。前者被成为非关系型数据库,后者有mysql、sqlserver他们都是关系型数据库,那么为什么会出现nosql这样类型的非关系型数据库呢?原因在于当前网站访问大,单个数据完全不够用,高并发的读写和高容量的存储都是当前web需要的特性,但是数据已经跟不上节奏了,那么nosql也应运而生。

nosql数据库的优势在于易扩展、高数据、高性能、灵活的数据类型、高可用。

2、Redis介绍

Redis是NoSql类型数据库的一种,全称是REmote Dictionary Server(远程字典服务器)是开源免费的,是一个高性能的(key/value)分布式内存数据库,是当前最热门的NoSql数据库之一

与其他key-valve的缓存产品相比具有以下三点

  1. Redis支持数据的持久化,可以将内存中的数据 保持在磁盘中,重启的时候可以再次加载进行使用
  2. Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储
  3. Redis支持数据的备份,即master-slave(主从)模式的数据备份

相比而言Redis更具有优势

  1. 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  2. 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  3. 原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
  4. 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性
  5. 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不 用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
  6. 使用多路I/O复用模型,非阻塞IO;

Redis的应用场景也较为广泛

  • 聊天室在线好友列表
  • 任务队列(比如说抢购,秒杀,买票)
  • 排行榜
  • 数据过期处理
  • 分布式集群架构中的session问题

Redis数据结构

Redis是一种基于内存的数据库,并且提供一定的持久化功能,它是一种键值(key-value)数据库,使用 key 作为 索引找到当前缓存的数据,并且返回给程序调用者。 当前的 Redis 支持 6 种数据类型,它们分别是字符串(String)、列表(List)、集合(set)、哈希结构 (hash)、有序集合(zset)和基数(HyperLogLog)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XgBF5YwF-1634871961905)(D:\桌面\笔记\截图\1634870260250.png)]

Redis常用指令

学习网站http://doc.redisfans.com/index.html

Redis的事务管理

Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证: 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。

事务在执行的过程中,不会被其他客 户端发送来的命令请求所打断。

事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

一个事务从开始到执行会经历以下三个阶段: 开始事务。 命令入队。 执行事务。

语法: 以multi命令开始 多条命令进入事务 最后由exec命令一并执行事务中所有的命令

ip:port> multi(开始事务)
OK
ip:port> set stu1 name1
QUEUED
ip:port> set stu2 name2
QUEUED
ip:port> set stu3 name3
QUEUED
ip:port> exec
1)OK
2)OK
3)OK

Redis发布订阅模式

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。 Redis 客户端可以订阅任意数量的频道。

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

请添加图片描述

在我们实例中我们创建了订阅频道名为 redisMessage:
127.0.0.1:6379> subscribe redisMessage
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisMessage"
3) (integer) 1


重新开启个 redis 客户端,然后在同一个频道 redisMessage 发布两次消息,订阅者就能接收到消
息。
127.0.0.1:6379> publish redisMessage "demo1 test"
(integer) 1
127.0.0.1:6379> publish redisMessage "demo2 test"
(integer) 1
127.0.0.1:6379> publish redisMessage "demo3 test"
(integer) 1



订阅者的客户端会显示如下消息
127.0.0.1:6379> subscribe redisMessage
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisMessage"
3) (integer) 1
1) "message
2) "redisMessage"
3) "demo1 test"
1) "message"
2) "redisMessage"
3) "demo2 test"
1) "message"
2) "redisMessage"
3) "demo3 test"

Jedis连接Redis

idea创建Maven项目,导入依赖

<dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>3.3.0</version>
    </dependency>

(一)单实例连接

核心代码

public  void testA(){
        Jedis jedis = new Jedis("192.168.3.46",6379);
        jedis.set("key1","张三");
        String key1 = jedis.get("key1");
        System.out.println(key1);
    }

执行代码需要注意的是虚拟机连接的ip是127.0.0.1:6379 意思是连接的本机,其他机器无法连接,这里需要修改配置文件,将连接地址改为虚 拟机的地址,就可以了. 修改redis.conf文件里面的 bind 连接地址,将连接地址改为自己虚拟机的ip bind 192.168.3.46 重启服务

(二)连接池连接

 //1、创建连接池配置文件对象
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(10);
        jedisPoolConfig.setMaxTotal(20);
        JedisPool jedisPool =null;
        Jedis jedis =null;
        try {
            //2、创建连接池
            jedisPool = new JedisPool(jedisPoolConfig,"192.168.3.46",6379);
            //3、获取数据源
            jedis = jedisPool.getResource();
            //4、写入数据
            jedis.set("key1","stu1");
            //5、获取数据
            System.out.println(jedis.get("key1"));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
            if (jedisPool != null) {
                jedisPool.close();
            }
        }

Redis持久化方式

什么是持久化?

redis的值是放在内存中的,但是内存有一个特性就是随着断电或者关机,内存数据丢失,那么为了防止突发情况导致数据丢失,将会对redis数据进行备份,即按照一定的触发条件进行数据保存到硬盘中。

持久化方式

1、RDB持久化

RDB 是以二进制文件,是在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化 的文件,达到数据恢复。 优点:使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能 缺点:RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合 数据要求不严谨的时候 这里说的这个执行数据写入到临时文件的时间点是可以通过配置来自己确定的,通过配置redis 在 n 秒内如果超过 m 个 key 被修改这执行一次 RDB 操作。这个操作就类似于在这个时间点来保存一次 Redis 的所有数据,一次快照 数据。所有这个持久化方法也通常叫做 snapshots。 RDB 默认开启,redis.conf 中的具体配置参数如下;

#dbfilename:持久化数据存储在本地的文件
dbfilename dump.rdb
#dir:持久化数据存储在本地的路径,如果是在/redis/redis-5.0.5/src下启动的redis-cli,则数据会存储在当前
src目录下
dir ./
##snapshot触发的时机,save
##如下为900秒后,至少有一个变更操作,才会snapshot
##对于此值的设置,需要谨慎,评估系统的变更操作密集程度
##可以通过“save”来关闭snapshot功能
#save时间,以下分别表示更改了1个key时间隔900s进行持久化存储;更改了10个key300s进行存储;更改10000个
key60s进行存储。
save 900 1
save 300 10
save 60 10000
##当snapshot时出现错误无法继续时,是否阻塞客户端“变更操作”,“错误”可能因为磁盘已满/磁盘故障/OS级别异常等
stop-writes-on-bgsave-error yes
##是否启用rdb文件压缩,默认为“yes”,压缩往往意味着“额外的cpu消耗”,同时也意味这较小的文件尺寸以及较短的网
络传输时间
rdbcompression yes
AOF持久化

Append-Only File,将“操作 + 数据”以格式化指令的方式追加到操作日志文件的尾部,在 append 操作返回后(已经 写入到文件或者将要写入),才进行实际的数据变更,“日志文件”保存了历史所有的操作过程;当 server 需要数据 恢复时,可以直接 replay 此日志文件,即可还原所有的操作过程。

AOF 相对可靠,AOF 文件内容是字符串,非常 容易阅读和解析。

优点:可以保持更高的数据完整性,如果设置追加 file 的时间是 1s,如果 redis 发生故障,最多会丢失 1s 的数 据;且如果日志写入不完整支持 redis-check-aof 来进行日志修复;AOF 文件没被 rewrite 之前(文件过大时会对 命令进行合并重写),可以删除其中的某些命令(比如误操作的 flushall)。

缺点:AOF 文件比 RDB 文件大,且恢复速度慢。

同时需要提醒,如果你的 redis 持久化手段中有 aof,那么在 server 故障失效后再次启动前,需要检测 aof 文件的完整性。 AOF 默认关闭,开启方法,修改配置文件 reds.conf:appendonly yes


##此选项为aof功能的开关,默认为“no”,可以通过“yes”来开启aof功能
##只有在“yes”下,aof重写/文件同步等特性才会生效
appendonly yes
##指定aof文件名称
appendfilename appendonly.aof
##指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec
appendfsync everysec
##在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no”
no-appendfsync-on-rewrite no
##aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”,建
议“512mb”
auto-aof-rewrite-min-size 64mb
##相对于“上一次”rewrite,本次rewrite触发时aof文件应该增长的百分比。
##每一次rewrite之后,redis都会记录下此时“新aof”文件的大小(例如A),那么当aof文件增长到A*(1 + p)之后
##触发下一次rewrite,每一次aof记录的添加,都会检测当前aof文件的尺寸。
auto-aof-rewrite-percentage 100

9.2.3 AOF与RDB区别 RDB: RDB是在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据 恢复。

优点:使用单独子进程来进行持久化,主进程不会进行任何IO操作,保证了redis的高性能

缺点:RDB是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失。所以这种方式更适合 数据要求不严谨的时候

redis哨兵模式

哨兵模式:给集群分配一个站岗的。 哨兵的作用就是对Redis系统的运行情况监控,它是一个独立进程

它的功能: 1. 监控主数据库和从数据库是否运行正常;

  1. 主数据出现故障后自动将从数据库转化为主数据库;

需要注意的是:主从集群:主机有写入权限。从机没有,只有可读。

Redis高端面试-缓存穿透,缓存击穿,缓存雪 崩问题 、 分布式锁

缓存雪崩

原因:存储在redis中的key大量过期了,导致同一时间数据库并发量增大,严重可能导致数据库宕机,造成系统崩溃

解决办法:1、给其他线程加锁或者队列来控制数据库读写缓存的线程数量

​ 2、分析行为,不同的key设置不同的过期时间,让缓存失效时间均匀

缓存穿透

原因: 用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。

解决方案: 1.如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问 数据库,这种办法最简单粗暴。

2.把空结果,也给缓存起来,这样下次同样的请求就可以直接返回空了,既可以避免当查询的值为空时引起的缓存 穿透。同时也可以单独设置个缓存区域存储空值,对要查询的key进行预先校验,然后再放行给后面的正常缓存处 理逻辑。

缓存击穿

对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。 这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是 很多key。

热点key: 某个key访问非常频繁,当key失效的时候有大量线程来构建缓存,导致负载增加,系统崩溃。 解决办法: 1、使用锁,单机用synchronized,lock等,分布式用分布式锁。

2、缓存过期时间不设置,而是设置在key对应的value里。如果检测到存的时间超过过期时间则异步更新缓存。

分布式锁

使用分布式锁要满足的几个条件
  1. 系统是一个分布式系统(关键是分布式,单机的可以使用ReentrantLock或者synchronized代码块来实现)
  2. 共享资源(各个系统访问同一个资源,资源的载体可能是传统关系型数据库或者NoSQL)
  3. 同步访问(即有很多个进程同时访问同一个共享资源。)
分布式锁、线程锁、进程锁区别:

线程锁:主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码 段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如 synchronized是共享对象头,显示锁Lock是共享某个变量(state)。 进程锁:为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程 的资源,因此无法通过synchronized等线程锁实现进程锁。 分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。

使用redis的setNX命令实现分布式锁

线程锁:主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码 段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如 synchronized是共享对象头,显示锁Lock是共享某个变量(state)。 进程锁:为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程 的资源,因此无法通过synchronized等线程锁实现进程锁。 分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。

使用redis的setNX命令实现分布式锁

实现的原理 Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端对Redis的连接并不存在竞争 关系。redis的SETNX命令可以方便的实现分布式锁。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值