Redis

介绍

  Redis是一款非关系型数据库,将数据以键值对的方式存储在内存中,读写速度非常快,可支持多种数据类型,还支持数据持久化。
什么是关系型数据库?
  关系型数据库通过关系模型来创建数据库。关系模型就是“一对一,一对多,多对多”等关系模型。
关系型数据库安全(存储在硬盘上),容易理解(二维表的结构贴近现实),易于维护,数据库的ACID属性,大大降低了数据冗余和数据不一致的概率。但是海量数据的读写对于传统关系型数据库来说,硬盘IO是一个很大的挑战。
  关系型数据库最大的优点就是事务的一致性,这个特性,使得关系型数据库可以适用于一切要求一致性比较高的系统中。比如:银行系统。但是在网页应用中,对这种一致性要求不是那么严格,允许有一定的时间间隔,所以关系型数据库的特点不是那么重要。关系型数据库为了维护一致性所付出的巨大代价就是读写性能非常差。像微博,脸书这类应用,对于并发读写能力要求极高,关系型数据库已经无法应付。所以必须要一种新的数据结构存储来代替关系型数据库。所以非关系型数据库应运而生。
什么是非关系型数据库?
  NoSQL非关系型数据库,主要指那些非关系的,分布式的,且一般不保证ACID的数据存储系统,主要代表就是Redis.。NoSQL提出了一种存储方式,以键值来存储,不需要像关系型数据库那样要进行多表查询,仅仅只需通过key来获取对应的value值即可。

Redis作用

1、缓存: 合理利用缓存不仅能够提升网站的访问速度,还能大大降低数据库的压力。Redis提供了键的过期策略,也提供了灵活的键淘汰策略,所以,现在Redis用在缓存的场合非常多。
2、排行榜: 很多网站都有排行榜应用,如淘宝的月度销量榜单,Redis提供的有序数据结构能实现复杂的排行榜应用。
3、计数器: 什么是计数器,如电商平台的浏览量,视频网站视频的播放数等等。为了保证数据实时性,每次浏览都需要加1,并发量高的时候对数据库是一种压力。Redis提供的incr命令来实现计数器功能,内存操作,性能非常好,非常适合计数场景
4、数据排重: 利用Redis的Set数据结构,我们可以方便地实现数据去重,并确保数据的唯一性。
5、分布式锁: 在很多互联网公司中都使用了分布式技术,分布式技术带来的技术挑战是对同一个资源的并发访问,如全局ID、减库存、秒杀等场景,并发量不大的场景可以使用数据库的悲观锁、乐观锁来实现,但在并发量高的场合中,利用数据库锁来控制资源的并发访问是不太理想的,大大影响了数据库的性能。可以利用Redis的setnx功能来编写分布式的锁,如果设置返回1说明获取锁成功,否则获取锁失败,实际应用中要考虑的细节要更多。
这里只是简单的提一下,后续会写博客实现这些功能

Redis线程模型

Redis是单线程模型还是多线程模型?
6.0版本之前,是单线程模式的,处理客户端请求和读写操作都是一个线程来完成的。
6.0版本之后,采用了多线程模式,将与客户端请求部分采用多线程处理,执行读写命令仍采用单线程处理,所以,依然是线程安全的。

为什么设计成单线程模型速度也很快?
1.基于内存操作,Redis的数据存储在内存中,访问速度比较快
2.底层存储结构是一个哈希表,可以通过key获取hash值,快速定位
3.避免上下文的切换,因为是单线程模型,避免了不必要的上下文切换和多线程竞争

Redis持久化

Redis的数据存储在内存中,有可能产生丢失,所以Reid提供了持久化机制

RDB方式:
RDB方式是默认的持久化方式,是以快照的方式将Reids中的数据保存到一个rdb文件中。
触发保存快照的规则:在reids.conf中有一个save命令可以触发持久化。比如:“save m n”,表示在m秒内数据集存在n次修改就会触发RDB持久化
关闭RDB持久化:通过注释所有的save命令来关闭RDB持久化方式
另外在客户端中可以通过save命令触发rdb持久化。
这里就可以提出一个问题了,如何触发rdb持久化,一个就是配置文件中的save命令触发,另一个就是通过redis客户端进行主动触发。

AOF方式:
以日志的形式记录写操作命令,回复命令时逐行执行命令即可恢复数据。
因为AOF默认不开启,所以我们要在配置文件中开启,我们将配置文件中默认的appendonly no修改为yes即可开启。另外appendfilename "appendonly.aof"指定存储日志的文件。
触发AOF的方式:
appendfsync always 每进行一次写操作就会触发,性能消耗大
appendfsync everysec 每秒存储一次,会产生数据丢失

Redis和MySQL如何保证数据一致

有一个场景,有一个当Redis和MySQL中共有的数据进行改变,如何操作保证数据的一致性?
1.先更新MySQL,再更新Redis。
例如下面这种场景,假设客户端1将mysql中的数据修改称为9。此时客户端2查询redis中的数据时,查询到10,此时数据库中的数据为9,但是在redis中查询结果为10。这种情况由于两次更新不能立刻成功导致某些请求钻了空子。

2.先更新Redis,再更新MySQL。
假如还是上述情况,只不过操作2和操作5的顺序换一下。首先客户端1将Redis中的数据修改称为9,此时客户端2访问Redis,由于Redis中的数据已经被修改了,所以客户端2查到了9,但是此时数据库中的数据为10。一二两种情况都是由于两次更新操作不能同步完成,导致其他请求钻了空挡。
3.先删除缓存,再更新数据库。
下面场景,客户端1首先删除缓存,然后客户端2发现缓存中没有数据,从数据库中查询到数据缓存之Redis,然后拿到10,最后客户端1将MySQL中的数据修改为9,此时Redis中数据为10,数据不一致

4.先更新数据库,再删除缓存
假如还是上述场景,将操作2和操作5交换。客户端1首先将数据库中的数据修改为9,此时客户端2查询Redis,查询到原来数据库的缓存10,此时MySQL中的数据为9,数据不一致。
5.延时双删:先删除缓存,再更新数据库,再删除缓存
首先这种方式可以保证MySQL和Redis的数据一致性。我们来讲讲为什么第二次缓存删除为什么不能直接删除,而是延时呢?举例子嘛:假设第四步很慢,很慢,第二次删除都结束了还没有将数据缓存到Redis中,此时客户端2拿着原来MySQL中的就数据更新到缓存中会导致数据不一致。
延时双删由于有延时,所以会影响系统性能。

Redis事务

前面了解到Redis读写操作不是单线程的吗?为什么还需要Redis事务?j
假设有一个场景,我想要向Redis中同时存储几条指令,可能这几条指令之间还有顺序性,不能导致执行顺序打乱,此时就需要Redis事务了。

Redis事务是一组命令的集合,
事务执行过程中,会按照顺序执行,
所有在事务中的命令不会立即执行,
事务在执行的过程中,不会被其他客户端发来的请求打断
事务中的某条指令发生错误不会影响其他指令的执行
Redis中的事务操作:开启事务(multi),执行事务(exec),执行事务前可以通过discard放弃事务

主从复制

使用一个Redis实例作为主机,其余作为备份机,主机和备份机的数据完全一致,主机支持数据的写入和读取等各项操作,而从机只支持与主机数据的同步和读取。客户端将数据写入主机,由主机自动将数据写入到从机。
主从复制解决了数据备份问题,并且由于主机只负责写入和同步至从机操作,从机负责同步和读取操作,从而达到了读写分离的目的,降低了Redis压力。

主从复制的作用主要包括:
1.数据备份,Redis的持久化方式无法保证Redis数据的完整性,而每台Redis机器中的数据都是一致的,保证了数据的备份。
2.故障恢复:当主节点出现了问题,可以由从节点提供服务,实现快速的故障恢复
3.负载均衡:在主从复制的基础上,配合读写分离,分担Redis压力;
4.高可用基石:除了上述操作,主从复制还是哨兵和集群能够实施的基础,所以说主从复制是高可用基石。

哨兵机制

在Redis集群中可以配置哨兵进程,哨兵定期会给每个Redis服务发送命令,如果能接收到响应,说明Redis服务正常,否则Redis服务故障。哨兵的重点在于监测主机,一旦主机发生故障,哨兵机制会从从机中选举一个作为主机。
除了监控各个Redis服务器之外,哨兵之间也会相互监控。

key的过期策略

1.惰性删除:某个键在过期之后,此键不会马上被删除,而是等到下次被使用的时候,才会检查到已过期,此时才会被删除。所以惰性删除非常占用内存,还要维护状态保存键是否过期
2.定期删除:每隔一段时间,会扫描一定数量的键,并清除已经过期的键。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以使得CPU和内存资源达到最优的平衡效果
Redis中使用了惰性删除和定期删除两种过期策略

缓存穿透

首先来了解一下,数据查询处理流程
前台请求,首先从缓存中获取数据,如果存在直接返回,如果没有,从数据库中取数据,然后将数据更新到缓存中,并返回结果。如果数据库中也没有数据,那就返回空结果。
缓存穿透就是一句话:数据库没有,缓存中没有。
比如查询一个不合法的id,每次查询请求都会到达数据库,从而导致数据库直接暴露,并发量高的情况下可能会压垮数据库。
解决方案:
1.对参数进行校验,不合法数据就行拦截
2.可以在Redis中设置key-null,下次请求的时候久不会再走数据库了。这种请求会给空对象设置一个较短的过期时间

缓存击穿

某个key对应的数据在数据库中存在,但在Redis中某个时间点过期了,此时如果有大量的请求访问,发现key过期,都会从数据库中拿数据,这时候大量的请求可能会压垮数据库。
解决方案:
1.热点数据设置永不过期,或者不能再访问量大的时候过期
2.枷锁,在第一个请求到来的时候使用互斥锁锁住,其他的请求等待,等到第一个请求拿到了数据然后缓存到Redis中。后面的请求发现已经有缓存了,便会直接从缓存中取数据。

缓存雪崩

在高并发情况下,大量的缓存失效,或者缓存出现故障。由于大量的请求会到达数据库,数据库的调用会暴增,这样就可能会导致数据库宕机。
解决方案:
1.随机设置key的过期时间,避免大量的key集体失效。
2.如果是集群部署,可将热点数据均匀分布在不同的Redis上能够避免缓存故障的情况
3.跑定时任务,在缓存失效前刷进新的缓存。

真正的大师永远都怀着一颗求学的心。

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值