什么是Redis?它主要用来什么的?
与MySQL数据库不同的是,Redis的数据是存在内存中的。它的读写速度非常快,。因此redis被广泛应用于缓存,另外,Redis也经常用来做分布式锁
为什么Redis需要把所有数据存放到内存中
Redis为了达到最快的读写速度,将数据都读到内存中,并通过异步的方式将数据写入磁盘,所以Redis具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度为严重影响Redis的性能
Redis特征
●键值(key-value) 型,value支持多种不同数据结构,功能丰富
●单线程, 每个命令具备原子性
●低延迟,速度快(基于内存、10多路复用、良好的编码)。
●支持数据持久化
●支持主从集群、分片集群
●支持多语言客户端
Redis基本数据类型
基本数据类型:Sting(字符串) Hash(哈希) List(列表)
Set(集合)特点:无序 元素不可重复 查找快 支持交集、并集、差集等功能
Zset(有序集合)特点:可以排序 元素不可重复 查找快
特殊类型:
GEO 例如: {A: (120.3,30.5) } (经纬度)
BitMap 例如: 0110110101110101011
HyperLog 例如: 0110110101110101011
Redis常用客户端
客户端 | 基本实现 |
---|---|
Jedis | Jedis实例是线程不安全的,多线程环境下需要基于连接池来使用 |
lettuce | Lettuce是基于Netty实现的,支持同步、异步和响应式编程方式, 并且是线程安全的。支持Redis的哨兵模式、集群模式和管道模式。 |
Redisson | Redisson是一个基于Redis实现的分布式、可伸缩的Java数据结构集合。 包含了诸如Map. Queue、Lock、Semaphore、Atomi cLong等强大功能 |
为什么Redis 6.0 之后改多线程呢?
Redis是单线程的,但是6.0之后redis的瓶颈并不在CPU,而在内存的操作和网络I/O。内存不够的话,可以扩大机器内存或者做数据结构压缩优化,真正致命的是网络I/O性能,网络I0的读写在redis整个执行期间占用了大部分的时间,6.0后把这里改成多线程处理方式,对整个redis的性能会有很大的提升。
,而核心的命令执行还是单线程
Redis应用场景
1.缓存
2.数据共享分布式
3.分布式锁
4.计数器
5.限流
6.消息队列
7.抽奖
8.打卡签到点赞
Redis持久化
AOF:采用日志的形式来记录每个写操作,追加到AOF文件的末尾
RDB:把内存数据以快照的形式保存到磁盘上
AOF的三种策略:
Always:同步写回,每个子命令执行完,都立即将日志写回磁盘。
Everysec:每个命令执行完,只是先把日志写到AOF内存缓冲区,每隔一秒同步到磁盘。
No:只是先把日志写到AOF内存缓冲区,有操作系统去决定何时写入磁盘。
三种策略优缺点:
always同步写回,可以基本保证数据不丢失,
no策略则性能高但是数据可能会丢失,
一般可以考虑折中选择everysec。
两种持久化的比较: RDB:因为是生成的镜像,所以在回复的时候比较快,但是因为不像是aof可以保证一致性。
AOF:因为是以日志的形式,所以一致性较高,但是因为文件较大,所以在恢复的时候比较慢。
所以常见的方式是两种持久化方法的结合,RDB记录一大部分,aof保证一致性。
Redis高可用实现
高可用一般来说有两个含义:一是数据尽量不丢失,二是保证服务尽可能可用
主从:主从模式做到了数据冗余,数据拥有备份,当主节点发生故障时,可以选择一个slave节点继续提供服务(但是主从模式没有解决怎么选择slave节点作为master节点的方法,无法保证高可用)。
优点:
1)实现读写分离,降低master节点的读数据压力,提高系统的性能。写操作交给master节点,读操作交给slave节点,提供多个副本。
2)配置简单,容易搭建。只需要在slave节点上维护master节点的地址信息就可实现。缺点:
1)当master节点宕机时,由于无法选择哪一个slave节点当master节点,无法保证高可用。
2)所有的写数据的压力都集中在master节点,没有解决master节点写的压力。
哨兵:监控、通知和自动故障转移。
优点:哨兵机制,保证高可用。能够监控各个节点运行状况,进行自动故障转移。
缺点:
1)中心化集群实现方式,基于主从模式,切换节点时,会发生数据的丢失。
2)集群里所有节点保存的都是全量数据,浪费内存空间,没有真正实现分布式存储。数据量过大时,主从同步严重影响master的性能。
3)数据写的操作都集中在master上,仍然没有解决master写数据的压力。
集群:哨兵模式基本已经实现了高可用,但是每个节点都存储相同的内容,很浪费内存。而且,哨兵模式没有解决master写数据的压力。为了解决这些问题,就有了集群模式,实现分布式存储,每个节点存储不同的内容。集群部署的方式能自动将数据进行分片,每个master上放一部分数据,提供了内置的高可用服务,即使某个master宕机了,服务还可以正常地提供。
优点:
1)无中心结构,部署简单。所有的Redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
2)可扩展性,可扩展master节点,释放单个master的写数据压力,节点可动态添加或删除。
3)能够实现自动故障转移,节点之间通过gossip协议交换状态信息,用投票机制完成slave到master的角色转换。
Redis 分布式锁
原理:所有服务中的所有线程都去获取同一把锁,但只有一个线程可以成功的获得锁,其他没有获得锁的线程必须全部等待,直到持有锁的线程释放锁
Redis 分布式锁主要有以下特点:
1)互斥性是分布式锁的重要特点,在任意时刻,只有一个线程能够持有锁;
2)锁的超时时间,一个线程在持锁期间挂掉了而没主动释放锁,此时通过超时时间来保证该线程在超时后可以释放锁,这样其他线程才可以继续获取锁;
3)加锁和解锁必须是由同一个线程来设置;
4)Redis 是缓存型数据库,拥有很高的性能,因此加锁和释放锁开销较小,并且能够很轻易地实现分布式锁。
死锁:是指多个进程在运行过程中因争夺资源而造成的
解决方式:
1.确定线程获取锁定顺序
2.超时放弃获取该锁
Redis 事务机制
Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
Redis事务的主要作用就是串联多个命令防止别的命令插队。
事务特性:
1)单独的隔离操作
事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
2) 没有隔离级别的概念
队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行。
3) 不保证原子性
事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚。
缓存击穿、缓存穿透、缓存雪崩的问题以及解决方案
解决:
1.加互斥锁
保证线程的强一致性,性能差,只允许一条线程运行
2.逻辑过期
保证了高可用,性能高
解决:
1.缓存空数据,查询结果为空仍然把这个数据的空值进行缓存(可能导致数据库不一致的问题)
2.布隆过滤器 (存在误判:布隆过滤器数组越小,误判率越大)
解决:
1.利用redis集群提高服务的可用性
2.给缓存业务添加降级限流策略
————————————————————————————————————————
双写一致性
加分布式锁解决延迟双删存在脏数据的问题
————————————————————————————————————————
数据过期策略
————————————————————————————————————————
数据淘汰策略