Java Spring Cloud XV 之 Redis I
1.Redis简介
Redis 是完全开源免费的,遵守 BSD 协议,是一个灵活的高性能 key-value 数据结构存储,可以用来作为数据库、缓存和消息队列。
Redis 比其他 key-value 缓存产品有以下三个特点:
Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载到内存使用。
Redis 不仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。
Redis 支持主从复制,即 master-slave 模式的数据备份。
2.Redis 的特点
高性能: Redis 将所有数据集存储在内存中,可以在入门级 Linux 机器中每秒写(SET)11 万次,读(GET)8.1 万次。Redis 支持 Pipelining 命令,可一次发送多条命令来提高吞吐率,减少通信延迟。
持久化:当所有数据都存在于内存中时,可以根据自上次保存以来经过的时间和/或更新次数,使用灵活的策略将更改异步保存在磁盘上。Redis 支持仅附加文件(AOF)持久化模式。
数据结构: Redis 支持各种类型的数据结构,例如字符串、散列、集合、列表、带有范围查询的有序集、位图、超级日志和带有半径查询的地理空间索引。
原子操作:处理不同数据类型的 Redis 操作是原子操作,因此可以安全地 SET 或 INCR 键,添加和删除集合中的元素等。
支持的语言: Redis 支持许多语言,如 C、C++、Erlang、Go、Haskell、Java、JavaScript(Node.js)、Lua、Objective-C、Perl、PHP、Python、R、Ruby、Rust、Scala、Smalltalk 等。
主/从复制: Redis 遵循非常简单快速的主/从复制。配置文件中只需要一行来设置它,而 Slave 在 Amazon EC2 实例上完成 10 MM key 集的初始同步只需要 21 秒。
分片: Redis 支持分片。与其他键值存储一样,跨多个 Redis 实例分发数据集非常容易。
可移植: Redis 是用 C 编写的,适用于大多数 POSIX 系统,如 Linux、BSD、Mac OS X、Solaris 等。
3.Redis 与其他 key-value 存储有什么不同?
一、Redis 有着更为复杂的数据结构并且提供对它们的原子性操作,这是一个不同于其他数据库的进化路径。Redis 的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
二、Redis 运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样 Redis 可以做很多内部复杂性很强的事情。同时,因 RDB 和 AOF 两种磁盘持久化方式是不适合随机访问,因为它们是顺序写入的。
4.Redis 架构
Redis 主要由有两个程序组成:
Redis 客户端 redis-cli
Redis 服务器 redis-server
客户端、服务器可以位于同一台计算机或两台不同的计算机中。
5.缓存淘汰策略
Redis服务器繁忙时,有大量信息要保存
如果Redis服务器内存全满,再要往Redis中保存新的数据,就需要淘汰老数据,才能保存新数据
noeviction:返回错误**(默认)**
allkeys-random:所有数据中随机删除数据
volatile-random:有过期时间的数据库中随机删除数据
volatile-ttl:删除剩余有效时间最少的数据
allkeys-lru:所有数据中删除上次使用时间最久的数据
volatile-lru:有过期时间的数据中删除上次使用时间最久的数据
allkeys-lfu:所有数据中删除使用频率最少的
volatile-lfu:有过期时间的数据中删除使用频率最少的
6.缓存穿透
正常业务下,从数据库查询出的数据可以保存在Redis中
下次查询时直接从Redis中获得,大幅提高响应速度,提高系统性能
所谓缓存穿透,就是查询了一个数据库中都不存在的数据
我们Redis中没有这个数据,它到数据库查,也没有
如果这样的请求多了,那么数据库压力就会很大
前面阶段我们使用向Redis中保存null值,来防止一个查询反复穿透
但是这样的策略有问题
如果用户不断更换查询关键字,反复穿透,也是对数据库性能极大的威胁
使用布隆过滤器来解决这个问题
事先创建好布隆过滤器,它可以在进入业务逻辑层时判断用户查询的信息数据库中是否存在,如果不存在于数据库中,直接终止查询返回
7.缓存击穿
正常运行的情况,我们设计的应该在Redis中保存的数据,如果有请求访问到Redis而Redis没有这个数据
导致请求从数据库中查询这种现象就是缓存击穿
但是这个情况也不是异常情况,因为我们大多数数据都需要设置过期时间,而过期时间到时这些数据一定会从数据库中同步
击穿只是这个现象的名称,并不是不允许的
8.缓存雪崩
上面讲到击穿现象
同一时间发生少量击穿是正常的
但是如果出现同一时间大量击穿现象就会如下图
这种情况下,Mysql会短时间出现很多新的查询请求,这样就会发生性能问题
如何避免这样的问题?
因为出现这个问题的原因通常是同时加载的数据设置了相同的有效期
我们需要在设置有效期时添加一个随机数,大量数据就不会同时失效了,
9.Redis持久化
Redis将信息保存在内存
内存的特征就是一旦断电,所有信息都丢失,Redis来讲,所有数据丢失,就需要从数据库从新查询所有数据,这个是慢的
更有可能,Redis本身是有新数据的,还没有和数据库同步就断电了
所以Redis支持了持久化方案,在当前服务器将Redis中的数据保存在当地硬盘上
Redis恢复策略有两种
RDB:(Redis Database Backup)
数据库快照,(将当前数据库转换为二进制的数据保存在硬盘上),Redis生成一个dump.rdb的文件
我们可以在Redis安装程序的配置文件中进行配置
空白位置编写如下内容
save 60 5
60表示秒数,既1分钟
5表示key被修改的次数
配置效果:1分钟内如果有5个key以上被修改,就启动rdb数据库快照程序
优点:
因为是整体Redis数据的二进制格式,数据恢复是整体恢复的
缺点:
生成的rdb文件是一个硬盘上的文件,读写效率是较低的
如果突然断电,只能恢复最后一次生成的rdb中的数据
AOF(Append Only File):
AOF策略是将Redis运行过的所有命令(日志)备份下来
这样即使信息丢失,我们也可能根据运行过的日志,恢复为断电前的样子
它的配置如下
appendonly yes
特点:只保存命令不保存数据
理论上Redis运行过的命令都可以保存下来
但是实际情况下,Redis非常繁忙时,我们会将日志命令缓存之后,整体发送给备份,减少io次数以提高备份的性能和对Redis性能的影响
实际开发中,配置一般会采用每秒将日志文件发送一次的策略,断电最多丢失1秒数据
为了减少日志的大小
Redis支持AOF rewrite
将一些已经进行删除的数据的新增命令也从日志中移除,达到减少日志容量的目的