大家好,我又又又又又来啦!今天给大家介绍一下
redis
一、redis介绍
redis全称:Remote Dictionary Server(远程字典服务器)。是完全开源免费的,用C语言编写
的, 遵守BSD协议。是一个高性能的(key/value)分布式内存数据库,基于内存运行并支持持久化的NoSQL数据库,是当前最热门的NoSql数据库之一,也被人们称为数据结构服务器。
Redis是目前最流行的键值对(key-value)数据库,以出色的性能著称,官方提供的数据是可以支持100000以上的+QPS。Redis具有高性能的主要原因如下:
Redis是基于内存的存储数据库,绝大部分的命令处理只是纯粹的内存操作,内存的读写速度非常快,可存储多种数据类型,支持持久化,存储数据大,单个key和value可以存储到512M。
Redis是单进程线程的服务(实际上一个正在运行的Redis Server肯定不止一个线程,但只有一个线程来处理网络请求),避免了不必要的上下文切换,同时不存在加锁/释放锁等同步操作。
Redis使用多路I/O复用模型(select、poll、epoll),可以高效处理大量并发连接。
Redis中的数据结构是专门设计的,增、删、改、查等操作相对简单。
三大主线:
- 高性能:线程模型,数据结构,持久化,网络框架
- 高可靠性:主从复制,哨兵机制
- 高可拓展:数据分片,负载均衡
二、redis的两种持久化策略
redis中自身存在两种方案,分别叫RDB和AOF,来保障数据的持久化。其中前者默认开启,后者默认关闭。
redis是基于内存的,redis持久化的意思就是将redis数据,即内存数据写入磁盘等持久化存储设备当中。
RDB
RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。
手动开启方法
在redis客户端可以通过以下两个命令手动开启redis数据快照。
save(由redis主进程来执行RDB,会阻塞其他所有命令)
bgsave(开启子进程执行RDB,避免主进程受到影响)
在redis.conf中有被动触发的相应条件,且默认是bgsave。
原理
redis的主进程并不直接和真实物理地址打交道。它会维护一个页表的东西,页表记录着虚拟地址和物理内存中真实的物理地址之间的映射关系。子进程就是直接复制该页表,以此达到和主进程共享数据的效果。这个复制过程很快,是纳秒级别的,所以可以忽略不记。当子进程复制完页表后会读取内存数据并写入RDB文件。
当子进程在写入RDB文件时,主进程那依旧可以接受用户的请求并写数据。但是此时物理内存中的数据是只读模式,只是会拷贝一份数据出来让主进程可以在上面修改。主进程修改完后页表也会指向这个拷贝出来的新数据。这样就防止了子进程写入RDB,主进程那同时修改数据,从而产生的脏数据的问题。
AOF
AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。
开启与记录频率
在redis.conf文件里修改以下配置:
#是否开启AOF功能,默认是no
appendonly yes
#AOF文件的名称
appendfilename "appendonly.aof"
#表示每执行一次名令,立即记录到AOF文件
appendfsync always
#写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区写到AOF文件,是默认方案
appendfsync everysec
#写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no
Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在redis.conf中配置
#AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
#AOF文件体积最小多大以上才触发重写
auto-aof-rewrite-min-size-64mb
RDB和AOF的对比
RDB和AOF各有自己的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者来使用。
RDB默认开启,AOF默认关闭。RDB全称Redis Database Backup file,即Redis数据备份文件,也被叫做Redis数据快照。它整个是个二进制文件,在保存的时候体积是比较小的,恢复数据的速度比较快,但是它有可能会丢数据。
AOF全称是Append Only File。Redis处理的每一个写命令都会记录在这个AOF文件中,可以看做是一个命令日志文件。它整个文件的体积会比较大,所以恢复数据的速度会慢一些,但是它丢数据的风险要小很多。
一般在实际开发中我们都是结合两者去使用的。
RDB是一个快照文件,它是把redis内存存储的数据写到磁盘上,当redis实例宕机恢复数据的时候,方便从RDB的快照文件中恢复数据。
AOF的含义是追加文件,当redis操作写命令的时候,都会存储这个文件中,当redis实例宕机恢复数据的时候,会从这个文件中再次执行一遍命令来恢复数据。但是恢复的时候会很慢,所以我们一般都是使用RDB,因为我们对redis的定义就是缓存服务器,一般很重要的数据我们不会放在redis
那么如何redis的存储到达最大配置的时候,我们该怎么解决呢?
三、redis有几种淘汰策略
Redis的淘汰策略主要是指当内存达到最大配置时(maxmemory),Redis如何选择哪些数据淘汰以释放内存。Redis 提供了以下几种淘汰策略:
- noeviction 当达到最大内存时直接返回错误,不覆盖或逐出任何数据
- allkeys-lfu 淘汰整个 keyspace 中最不常用的 (LFU) 键 (4.0 或更高版本)
- allkeys-lru 淘汰整个 keyspace 最近最少使用的 (LRU) 键
- allkeys-random 淘汰整个 keyspace 中的随机键
- volatile-ttl 淘汰 expire set 中 TTL 最短的键
- volatile-lfu 淘汰 expire set 中最不常用的键 (4.0 或更高版本)
- volatile-lru 淘汰 expire set 中最近最少使用的 (LRU) 键
- volatile-random 淘汰 expire set 中的随机键
在配置文件中设置淘汰策略:
maxmemory-policy allkeys-lru
四、redis存储的数据类型
支持五种数据类型:字符串、哈希、列表、集合和有序集合,每种数据类型都有其特定的应用场景。合理使用Redis的数据类型可以提高应用程序的性能和可扩展性,选择合适的数据类型可以实现更快速、更可靠的数据处理和存储。
-
字符串(String):字符串是 Redis 最基础的数据类型,它存储的是二进制安全的数据,可以是数字、字符串或二进制数据。由于 Redis 的字符串是二进制安全的,因此可以用来存储图片、视频等二进制数据。应用场景包括缓存、配置信息等。
-
哈希(Hash):哈希是一种键值对集合,其中每个键都可以映射到一个或多个字段和值。哈希类型适用于存储对象,例如用户信息、商品详情等。通过使用哈希,可以更方便地对数据进行操作和查询。应用场景包括用户信息管理、商品详情管理等。
-
列表(List):列表是一种基于字符串的线性表数据结构,可以存储多个有序的字符串元素。列表适用于需要按照插入顺序排序的数据,例如消息队列、时间戳记录等。应用场景包括社交网络的时间线、任务队列等。
-
集合(Set):集合是一种无序的字符串集合,其中的每个元素都是唯一的,且没有重复的元素。集合适用于需要快速查找和删除的数据,例如用户标签、黑名单等。应用场景包括用户标签管理、黑名单管理等。
-
有序集合(Sorted Set):有序集合是一种特殊的集合,其中的每个元素都会关联一个分数,通过分数可以对集合进行排序。有序集合适用于需要按照分数排序的数据,例如评分排名、排行榜等。应用场景包括评分排名、热度排名等。
总的来说,Redis 的五种数据类型都提供了高效的存储和操作方式,可以满足各种应用场景的需求。通过合理的使用 Redis 的数据类型,可以极大地提高应用程序的性能和可扩展性。在实际应用中,根据具体需求选择合适的数据类型,可以实现更快速、更可靠的数据处理和存储。
说了这么多的好处,小伙伴们对redis有没有很心动丫
接下来我们就要说说redis有那些缺点了
五、redis容易出现的问题
1.缓存和数据库的双写一致性问题
数据的信息和缓存由于并发或者其中一个失败导致不一样
解决的方案:
1.我们一般是先修改数据库,再删除缓存,因为我们对redis的定位是缓存,redis可能会丢数据,首先保证我们的数据必须更新,如果redis删除失败,我们采用补偿策略。
2.使用消息中间件:我们把信息放入MQ,做消费补偿
2.缓存的并发竞争问题
多个子系统同事去set一个key。
解决方案:
1.做一个分布式锁。
3.缓存雪崩
当redis中的大量key集体过期,可以理解为Redis中的大部分数据都清空 / 失效了,这时候如果有大量并发的请求来到,Redis就无法进行有效的响应(命中率急剧下降),也会导致DB先生的绝望。
缓存雪崩的场景通常有两个:
- 大量热点key同时过期
- 缓存服务故障或宕机
结局方案:
- 保证redis高可用,建立redis集群
- 设置不同的过期时间,防止全部在同一时间过期
4.缓存击穿问题
缓存击穿是指:一条数据在查询的时候突然过期了,那么就所有的请求都打在数据库中
解决方法:
1.使用互斥锁,缓存失效的时候,先去获取锁。有锁去请求数据库,没锁就休眠一段时间重试。
2.采用异步更新的策略,不管有没有取到key对应的value,都返回结果。也就是异步起一个线程去数据库中更新缓存。
5.缓存穿透问题
缓存穿透是指:缓存和数据库中都没有数据,如果有人恶意访问的会先去缓存查询,此时缓存中无数据,后在数据库中去查询,数据库中也没有,这个时候会导致数据库宕机
解决方法:
接口校验
类似于用户权限的拦截,对于id = -3872这些无效访问就直接拦截,不允许这些请求到达Redis、DB上。
对空值进行缓存
比如,虽然数据库中没有id = 1022的用户的数据,但是在redis中对其进行缓存(key=1022, value=null),这样当请求到达redis的时候就会直接返回一个null的值给客户端,避免了大量无法访问的数据直接打在DB上。
但需要注意:
key设置的过期时间不能太长,防止占用太多redis资源,设置一个合适的TTL,比如两三分钟。
当遇到黑客暴力请求很多不存在的数据时,就需要写入大量的null值到Redis中,可能导致Redis内存占用不足的情况。
使用布隆过滤器
布隆过滤器的基本原理:使用BitMap结构和多个哈希函数,向其中加入数据x xx时将hash1(x),hash_1(x)hash1(x)、hash2(x)hash_2(x)hash2(x)、hash3(x)hash_3(x)hash3(x)等位置的bit值置为1。查询时,如果相应的位置均为1,则认为该数据存在于布隆过滤器中。性能较高但也有缺点:
可能会存在误判,使用时误判率可以作为参数进行设置,其实是调节了这个过程中使用到的哈希函数,使用的哈希函数越多,被误判的可能性越小,但相应地,判断过程会越慢。通常建议值是 1%。
不易于进行数据的删除操作,因为两个不同数据,可能会在某一个哈希函数上具有相同的哈希值
欲使其发挥作用,需要将MySQL中可能出现的所有参数、即全量数据都存入布隆过滤器中,代价较大
如果它告诉你不存在,则一定不存在;如果它告诉你存在,则可能不存在。
插一句:很适合判断海量元素中元素是否存在,比如设置网站的黑名单
使用BitMap作为布隆过滤器,将目前所有可以访问到的资源通过简单的映射关系放入到布隆过滤器中(哈希计算),当一个请求来临的时候先进行布隆过滤器的判断,如果有那么才进行放行,否则就直接拦截。
看到这里就结束啦,可以给我老凌一个三连暴击嘛,跪谢各位大哥!!!