Redis——简介

Redis

Redis本质上是一个Key-Value类型的内存数据库,很像memcached(分布式的高速缓存系统),不过数据可以持久化,而且支持的数据类型很丰富,有字符串,链表,集合和有序集合。支持在服务器端计算集合的并,交和补集(difference)等,还支持多种排序功能。所以Redis也可以被看成是一个数据结构服务器。

Redisd的整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。

Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB,不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能,比方说用他的List来做FIFO双向链表,实现一个轻量级的高性能消息队列服务,用他的Set可以做高性能的tag系统等等。另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一 个功能加强版的memcached来用。

Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算

Redis的常见的几种数据结构:

  • String:字符串
  • Hash: 哈希
  • List : 列表
  • set :集合
  • Zset :有序集合

缓存的优点:

  • 缓存以key-value的形式存储,查询性能要高于数据库
  • 缓存一般都存储在内存中,数据库的数据是存储在磁盘中的,在内存上操作效率要高于磁盘。
  • 缓存可扩展性比较高,更容易进行分布式部署。

缓存的分类:

  • 本地缓存
  • 分布式缓存
1 常见缓存的使用:
  • 本地缓存的常见使用:Spring的Cache、MyBatis的缓存
  • 分布式缓存的常见使用:Redis 和Memcached
(1)本地缓存:

SpringBoot中本地缓存的使用:
在这里插入图片描述
1)开启缓存
主启动器类上配置@EnableCaching

@SpringBootApplication
@EnableCaching
public class SpringcacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringcacheApplication.class, args);
    }
}

2)配置缓存

编写service,缓存的名称为score,缓存数据对应的键为"#score"

@Service
public class UserService {

    @Cacheable(cacheNames = "score",key="#score")
    public String getScore(int score){
        System.out.println("开始计算成绩");
        return score+"分";
    }
}

编写controller

@Controller
public class UserController {
    @Autowired
    UserService userService;

    @RequestMapping("/getscore")
    @ResponseBody
    public String getScore(int score){
        return userService.getScore(score);
    }
}

注:
配置@ResponseBody,返回类型为json形式

调用postman访问http://localhost:8080/getscore?score=59
在这里插入图片描述
前端打印:
在这里插入图片描述
后端打印:
在这里插入图片描述
当再次访问http://localhost:8080/getscore?score=59时,后端不再显示内容,说明缓存开始起作用了。

(2)分布式缓存

不同的项目操作的是同一个Redis,因此Redis对于整个项目来说是全局的(分布式的)。
在这里插入图片描述

1) Redis和Memcached的区别:
  • 存储方式不同:memchache把数据全部存在内存中,断电后会挂掉,数据不能超过内存大小;Redis有部分存在硬盘上,保证了数据的持久性。
  • 数据支持类型:memcache对数据类型支持相对简单;Redis有复杂的数据类型。
  • 存储大小不同:Redis最大可以达到512mb, memcache只有1mb;

注:
单机情况下使用Spring中的Cache,分布式环境下,使用Redis.

2 Redis的数据类型

Redis有5大基础数据类型:

  • String: 字符串类型
  • Hash: 字典类型
  • List: 列表类型
  • Set: 集合类型
  • ZSet: 有序集合类型
(1)字符串类型

字符串类型(Simple Dynamic Strings, SDS)——简单动态字符串,它是以键值对key-value的形式进行存储的,根据key来存储/获取value值。

使用:

set key1 hello ex 5   
get key1  
输出 hello

注:
ex 5 为5秒后过期

常见使用场景:

  • 存放用户(登录信息);
  • 存放文章详情和列表信息;
  • 存放和累计网页的统计信息;
(2)字典类型

字典类型(Hash)——散列类型/哈希表类型,它将一个key和一个特殊的“哈希表”关联起来,这个哈希表包含两列数据:字段和值。类似于Java中的Map<String,Map<String,String>>

使用:

hset h1 key1 v1  k2 word
hget h1 k2 
输出 word
(3)列表类型

列表类型(List)是一个使用链表结构存储的有序结构,它的元素插入会按照先后顺序存储到链表结构中,因此它的元素操作(插入和删除)时间复杂度为O(1),查找的时间复杂度为O(n)。

使用:

lpush list1 1 34 5 6
lpop list1 
输出19

列表的使用场景:

  • 消息队列:列表类型可以使用lpush实现先进先出的功能,同时又可以使用lpop弹出第一个元素,所以列表类型可以用来实现消息队列。
  • 文章列表:对于博客来说,当用户和文章较多时,为了加快程序的响应速度,我们可以将用户自己的文章放入List中,而List是有序的结构,我们可以实现分页功能,从而加速了程序的响应速度。
(4)集合类型

集合类型Set是一个无序并唯一的键值集合。

使用:

sadd set1 v1 v3 v4
smembers set1 
输出 v1 v3 v4

使用场景:

  • 微博中关注的人可以用集合存储,保证人员不会重复;
  • 中奖信息也可以用集合类型存储,保证一个人不会重复中奖;

集合类型Set和列表类型List的区别:

  • 列表可以存储重复元素,集合只能存储非重复的元素
  • 列表是按照元素的先后顺序存储元素的,而集合是无序方式存储元素的。
(5)有序集合类型

有序集合Sorted Set,相对于集合类型多了一个排序属性score(分值),对于有序集合ZSet来说,每个存储元素相当于有两个值组成,一个是元素值,一个是排序值。有序集合的元素不能重复,但是分值score可以重复。

使用:

zadd z1 30 xi  40 lao  50 gao
zrange z1 0 -1  # -1表示所有的
输出:xi  lao  gao

使用场景:

  • 学生成绩排名
  • 粉丝列表,根据关注的先后时间排序
3 Redis持久化

持久化就是数据从内存保存到磁盘的过程,目的就是为了防止数据丢失。因为内存中的数据在服务器重启后就会丢失,而磁盘中的数据则不会,因此为了系统的稳定,我们需要将数据进行持久化。同时持久化也是Redis和Memcached的最主要区别之一,因为Memcached是不支持持久化的。

Redis持久化的3种方式:

  • 快照方式(RDB,Redis DataBase):将某一时刻的内存数据,以二进制的方式写入磁盘。
  • 文件追加方式(AOF,Append Only File):记录所有的操作命令,并以文本的形式追加到文件中;
  • 混合持久化方法: Redis4.0之后新增的方式,混合持久化是结合了RDB和AOF的优点,在写入的时候,先把当前的数据以RDB的形式写入文件的开头,再将后续的操作命令以AOF的格式存入文件,这样既能保证Redis重启时的速度,又能降低数据丢失的风险。

持久化的策略设置
可以在reids-cli命令行中执行config set aof-use-rdb-preamble yes来开启混合持久化,当开启混合持久化时,Redis就以混合持久化的方式来作为持久化策略;当没有开启混合持久化时,使用config set appendonly yes 来开启AOF持久化策略,当AOF和混合持久化都没开启的情况下,默认使用RDB的持久化方式。

(1)RDB快照方式的优缺点

RDB优点:

  • RDB的内容为二进制的数据,占用内存更小,适合作为备份文件;
  • RDB对灾难恢复非常有用,可以更快的传输到远程服务器进行Redis服务恢复;
  • RDB可以更大程度的提高Redis的运行速度,因为每次持久化时主进程都会fork()一个子进程,进行数据持久化到磁盘,Redis主进程并不会执行磁盘的I/O等操作;
  • 与AOF格式的文件相比,RDB文件可以更快的重启。

RDB缺点:

  • RDB只能保存某个时间间隔的数据,如果中途Redis服务被意外终止了,则会丢失一段时间的Redis数据
  • RDB需要经常fork()才能使用子进程将其持久化到磁盘上。如果数据集比较大,fork()可能会很耗时,如果数据集很大,而CPU的性能欠佳,则可能导致Redis停止为客服端服务几毫秒。

注:

  • fork()是创建进程函数。一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
  • fork返回两个值,一个代表父进程,一个代表子进程:代表父进程的值是一串数字,这串数字是子进程的ID(地址);一个代表子进程,值为0。
(2)文件追加方式AOF的优缺点

AOF优点:

  • AOF持久化保存的数据更加完整,AOF提供了三种保存策略,每次操作保存、每秒保存一次、跟随系统的持久化策略保存。其中每秒保存一次,从数据的安全性和性能两方面考虑是一个不错的选择,也是AOF默认的策略,即使发生了意外的情况,最多只会丢失1s钟的数据;
  • AOF采用的是命令缀加写入的方式,所以不会出现文件损坏的问题,即使由于某些意外原因导致了最后操作的持久化数据只写入了一半,也可以通过redis-check-aof工具进行修复。
  • AOF持久化文件非常容易理解和解析,它把所有Redis键值操作命令,以文件的方式存入了磁盘。即使不小心用flushall删除了所有的键值信息,只要在AOF文件中删除最后的flushall命令,重启Redis即可恢复之前误删的数据。

AOF缺点:

  • 对于相同的数据集来说,AOF文件大于RDB文件
  • 在Redis负载比较高的情况下,RDB要比AOF的性能要好
  • RDB使用快照的形式持久化整个Redis数据,而AOF只是将每次执行的命令追加到AOF文件中,因此理论上说,RDB比AOF更加健壮。
(3)混合持久化的优缺点

混合持久化优点:

  • 混合持久化结合了RDB和AOF持久化的优点,开头以RDB的格式,使得Redis可以更快的启动,同时结合AOF的优点,降低了大量数据丢失的风险。

混合持久化的缺点:

  • AOF文件中添加了RDB格式的北荣,使得AOF文件的可读性变差
  • 兼容性比较差,如果开启了混合持久化,那么Redis 4.0之前的版本是不支持的。
4 常见的缓存问题
(1)缓存雪崩

缓存雪崩是指在短时间内,有大量的缓存同时过期,导致大量的请求直接查询数据库,从而对数据库造成了巨大的压力,严重情况下可能会导致数据库宕机。

解决方法:
1)加锁排队
加锁排队可以起到缓冲的作用,防止大量的请求同时操作数据库,但缺点就是会增加系统的响应时间,降低系统的吞吐量,牺牲了一部分用户体验。

2)随机化过期时间
为了避免缓存同时过期,可以在设置缓存时额外添加一个随机时间,这样可以极大的避免大量的缓存同时过期。

int exTime = 60; //原本的过期时间

Random random = new Random();
//缓存设置
jedis.setex(cacheKey,exTime+random.nextInt(1000),value);

3)设置二级缓存
当Redis失效后,先去查询二级缓存。
在这里插入图片描述

(2)缓存穿透

缓存穿透是指查询缓存和数据库时都没有查询到数据,对于此类查询,因为在缓存中查不到数据,所以都会去数据库再次查询。

解决方法
1)缓存空结果
将数据库查询的结果保存到缓存中(包括空结果),为了提高用户体验,我们可以将空结果的缓存时间设置的短一些(3-5分钟),以防止用户长时间查询不到数据的情况。

(3)缓存击穿

缓存击穿是指某一时刻,某个热点缓存突然失效了,引起了大量的并发请求,对数据库造成了巨大压力。

解决方法:

  1. 加锁排队
    和缓存雪崩时的加锁排队方式一致,都是在查询数据库时进行加锁排队。

2)设置永不过期
对于某些热点缓存,我们可以设置永不过期,这样能保证缓存的稳定性,但需要注意在数据更改之后要及时更新热点缓存,不然会造成查询结果的误差。

(4)缓存预热

缓存预热是一个优化方案,用此来提高用户体验。缓存预热是指在系统启动的时候,先把查询结果预存到缓存中,以便用户以后查询时,可以直接从缓存中读取,以节约用户的等待时间。

缓存预热的方案:

  • 将需要缓存的方法写到系统的初始化方法中,这样系统启动时就会自动加载数据并缓存数据。
  • 把需要缓存的方法加到某个页面或后端的接口上,手动触发缓存预热。
  • 设置定时任务,定时自动进行缓存预热
5 Redis集群

Redis的多机服务

  • Redis主从同步
  • Redis哨兵模式
  • Redis集群服务
(1)中从同步

主从同步是Redis高可用服务的基石,也是多机运行中最基础的一个。我们将主要存储数据的节点称为主节点(master),把通过复制主节点数据的副本节点称为从节点(slave).
在这里插入图片描述
主从同步的优缺点:
优点:

  • 性能方面:主从同步可以将查询任务分配给从服务器,主服务器主要用来执行写操作,这极大的提高了程序运行的效率,把所有的压力分摊到各个服务器了;
  • 高可用:当主服务器宕机后,可以迅速把从节点提升为主节点,为Redis服务器的宕机恢复节省了时间。
  • 防止数据丢失:当注服务器磁盘坏掉后,其他从服务器还保留着相关的数据,不至于数据全部丢失。

缺点:
当主节点崩溃后,需要人工干预才能恢复Redis的正常使用。

(2)哨兵模式

主从服务器节点较多的情况下,节点宕机需要人工恢复的难度比较大。因此我们需要一个自动工具——Redis Sentinel(哨兵模式)来把手动的过程变成自动的,让Redis拥有自动容灾恢复的能力。哨兵模式主要负责监控主从服务器的节点,当主从服务器节点出现问题的时候可以进行自动容灾恢复。
在这里插入图片描述

(3)Redis集群服务

Redis集群(Redis Cluster)是Redis多机运行的终极方案,它是Redis 3.0之后推出的服务,它的出现可以让我们完全抛弃主从同步和哨兵模式来实现Redis的多机运行。

  • redis集群采用 去中心化的方式(每个节点都会跟其他节点保持连接,用来交换彼此的信息)实现,无需proxy代理,客户端直接与redis集群的每个节点连接,根据同样的hash算法(哈希槽 (hash slot))计算出key对应的slot,然后直接在slot对应的redisj节点上执行命令。
  • redis cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉。

注:
每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值