概念: Redis (REmote Dlctionary Server)是用C语言开发的一个开源的高性能键值对(key-value)数据库。 特征: 1.数据间没有必然的关联关系
2.内部采用单线程机制进行工作 3.高性能。官方提供测试数据,50个并发执行100000个请求读的速度是110000次/s,写的速度是81000次/s。
4.多数据类型支持
字符串类型:string 列表类型:list 散列类型:hash 集合类型:set 有序集合类型:sorted_set
5.持久化支持。可以进行数据灾难恢复
Redis的应用
为热点数据加速查询(主要场景),如热点商品、热点新闻、热点资讯、推广类等高访问量信息等任务队列,如秒杀、抢购、购票排队等
即时信息查询,如各位排行榜、各类网站访问统计、公交到站信息、在线人数信息(聊天室、网站)、设备信号等
时效性信息控制,如验证码控制、投票控制等
分布式数据共享,如分布式集群架构中的session分离
消息队列
分布式锁
redis的优势和特点
- redis 数据读写速度非常快,因为它把数据都读取到内存当中操作,而且 redis 是用 C 语言编写的,是最“接近“”操作系统的语言,所以执行速度相对较快。
- redis 虽然数据的读取都存在内存当中,但是最终它是支持数据持久化到磁盘当中。
- redis 提供了丰富的数据结构。
- redis 的所有操作都是原子性,支持事务,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行。
- redis 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
Redis 的数据结构
集合(set):
set 是 string 类型的无序集合,不同于 list,set 中的元素不可以重复。
新的存储需求:存储大量的数据,在查询方面提供更高的效率
需要的存储结构:能够保存大量的数据,高效的内部存储机制,便于查询
set类型:与hash存储结构完全相同,仅存储键,不存储值(nil),并且值是不允许重复的
应用场景①:应用于随机推荐类信息检索,例热点歌单推荐,热点新闻推荐,热卖旅游线路,应用APP推荐,大V推荐等
应用场景②:共同好友,共同关注等等
解决方法:交并差集来实现
应用场景③:网站的访问统计
公司对旗下新的网站做推广,统计网站的PV(访问量),UV(独立访客),IP(独立IP)。
PV:网站被访问次数,可通过刷新页面提高访问量 UV:网站被不同用户访问的次数,可通过cookie统计访问量,相同用户切换P地址,
UV不变IP:网站被不同IP地址访问的总次数,可通过IP地址统计访问量,相同IP不同用户访问,IP不变
解决方案 利用set集合的数据去重特征,记录各种访问数据建立string类型数据,利用incr统计日访问量(PV)建立set模型,记录不同cookie数量(UV) 建立set模型,记录不同IP数量(IP)
应用场景④:同类型数据的快速去重
应用场景⑤:黑白名单
解决方案 基于经营战略设定问题用户发现、鉴别规则
周期性更新满足规则的用户黑名单,加入set集合 用户行为信息达到后与黑名单进行比对,确认行为去向
黑名单过滤P地址:应用于开放游客访问权限的信息源
黑名单过滤设备信息:应用于限定访问设备的信息源
黑名单过滤用户:应用于基于访问权限的信息源
哈希表(hash):
hash 类似于 java 中的 map,是一个键值对集合,在 redis 中可以用来存储对象。
应用场景①:电商网站购物车设计与实现,仅分析购物车的redis存储模型,添加、浏览、更改数量、删除、清空
以客户id作为key,每位客户创建一个hash存储结构存储对应的购物车信息将商品编号作为field,购买数量作
为value进行存储
添加商品:追加全新的field与value
浏览:遍历hash
更改数量:自增/自减,设置value值删除商品:删除field
清空:删除key
应用场景②:实现抢购
以商家id作为key 将参与抢购的商品id作为field 将参与抢购的商品数量作为对应的value抢购时使用降值的方式控制产品数量
列表(list):
list 是一个链表结构,主要功能是 push、pop 获取一个范围的所有值等等。操作中 key 理解为链表的名字。
数据存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分
需要的存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序
list类型:保存多个数据,底层使用双向链表存储结构实现
应用场景①:微信朋友圈点赞,要求按照点赞顺序显示点赞好友信息
应用场景②:可以做具有操作先后顺序的数据控制
应用场景③:twitter、新浪微博、腾讯微博中个人用户的关注列表需要按照用户的关注顺序进行展示,粉丝列表需要将最近关注的粉丝列在前面
应用场景④:新闻、资讯类网站如何将最新的新闻或资讯按照发生的时间顺序展示
应用场景⑤:企业运营过程中,系统将产生出大量的运营数据,如何保障多台服务器操作日志的统一顺序输出?
有序集合(sorted_set):
zset 和 set 一样,也是 string 类型的元素的集合,不同的是ZSET中的每个元素都会关联一个 double 类型的分数,zset 中的成员都是唯一的,但是所关联的分数可以重复。
新的存储需求:数据排序有利于数据的有效展示,需要提供一种可以根据自身特征进行排序的方式需要的存储结构:新的存储模型,可以保存可排序的数据 sorted_set类型:在set的存储结构基础上添加可排序字段
应用场景①:榜单类型排序的数据
字符串(string):
string 是 redis 中最基本的数据类型,redis 中的 string 类型是二进制安全的,即它可以包含任何数据,比如一个序列化的对象甚至一个图片(注意的是 redis 中的字符串大小上限是 512M)。
redis分布式缓存
1.什么是缓存(Cache)
定义:就是计算机内存中一段数据
2.内存中数据特点
1.读写快
2.断电立即丢失
3.缓存解决了什么问题?
- 1.提高网站吞吐量提高网站运行效率
- 2.核心解决问题:缓存的存在是用来减轻数据库访问压力
4.既然缓存能提高效率,那项目中所有数据加入缓存岂不是更好?
注意:使用缓存时一定 是数据库中数据极少发生修改,更多用于查询这种情况
5.本地缓存和分布式缓存区别?
-
本地缓存:存在应用服务器内存中数据称之为本地缓存 (local cache)
-
分布式缓存:存储在当前应用服务器内存之外数据称之为分布式缓存 (distribute cache)
-
集群:将同一种服务的多个节点放在一起共同对系统提供服务过程称之为集群
-
分布式:有多个不同服务集群共同对系统提供服务这个系统称之为分布式系统 (fistribute system)
Redis持久化
什么是持久化?
利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化。
为什么要进行持久化?
防止数据的意外丢失,确保数据安全性
持久化过程保存什么? 将当前数据状态进行保存,快照形式,存储数据结果,存储格式简单,关注点在数据 将数据的操作过程进行保存,日志形式,存储操作过程,存储格式复杂,关注点在数据的操作过程
持久化流程
既然redis的数据可以保存在磁盘上,那么这个流程是什么样的呢?
要有下面五个过程:
(1)客户端向服务端发送写操作(数据在客户端的内存中)。
(2)数据库服务端接收到写请求的数据(数据在服务端的内存中)。
(3)服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)。
(4)操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)。
(5)磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)。
这5个过程是在理想条件下一个正常的保存流程,但是在大多数情况下,我们的机器等等都会有各种各样的故障,这里划分了两种情况:
(1)Redis数据库发生故障,只要在上面的第三步执行完毕,那么就可以持久化保存,剩下的两步由操作系统替我们完成。
(2)操作系统发生故障,必须上面5步都完成才可以。
在这里只考虑了保存的过程可能发生的故障,其实保存的数据也有可能发生损坏,需要一定的恢复机制,不过在这里就不再延伸了。现在主要考虑的是redis如何来实现上面5个保存磁盘的步骤。它提供了两种策略机制,也就是RDB和AOF。
RDB机制
RDB其实就是把数据以快照的形式保存在磁盘上。什么是快照呢,你可以理解成把当前时刻的数据拍成一张照片保存下来。
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。
在我们安装了redis之后,所有的配置都是在redis.conf文件中,里面保存了RDB和AOF两种持久化机制的各种配置。
既然RDB机制是通过把某个时刻的所有数据生成一个快照来保存,那么就应该有一种触发机制,是实现这个过程。对于RDB来说,提供了三种机制:save、bgsave、自动化。我们分别来看一下
1、save触发方式
该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取。
2、bgsave触发方式
执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求
具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。
自动触发
自动触发是由我们的配置文件来完成的。在redis.conf配置文件中,里面有如下配置,我们可以去设置:
**①save:**这里是用来配置触发 Redis的 RDB 持久化条件,也就是什么时候将内存中的数据保存到硬盘。比如“save m n”。表示m秒内数据集存在n次修改时,自动触发bgsave。
默认如下配置:
#表示900 秒内如果至少有 1 个 key 的值变化,则保存save 900 1
#表示300 秒内如果至少有 10 个 key 的值变化,则保存save 300 10
#表示60 秒内如果至少有 10000 个 key 的值变化,则保存save 60 10000
不需要持久化,那么你可以注释掉所有的 save 行来停用保存功能。
**②stop-writes-on-bgsave-error :**默认值为yes。当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到灾难(disaster)发生了。如果Redis重启了,那么又可以重新开始接收数据了
**③rdbcompression ;**默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。
**④rdbchecksum :**默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
**⑤dbfilename :**设置快照的文件名,默认是 dump.rdb
**⑥dir:**设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名。
4、RDB 的优势和劣势
①、优势
(1)RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。
(2)生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
(3)RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
(4)RDB内部存储的是redis在某个时间点的数据快照,非常适合用于数据备份,全量复制等
应用:服务器中每X小时执行bgsave备份,并将RDB文件拷贝到远程机器中,用于灾难恢复。
②、劣势
RDB方式无论是执行指令还是利用配置,无法做到实时持久化,具有较大的可能性丢失数据
bgsave指令每次运行要执行fork操作创建子进程,要牺牲掉一些性能
Redis的众多版本中未进行RDB文件格式的版本统一,有可能出现各版本服务之间数据格式无法兼容现象
RDB三种启动机制对比
save 读写是同步的,会阻塞客户端指令,不会额外消耗内存,不会开启新进程
bgsave 读写是异步的,不会阻塞客户端指令,会额外消耗内存,会开启新进程
AOF
RDB存储的弊端
-
存储数据量较大,效率较低
-
基于快照思想,每次读写都是全部数据,当数据量巨大时,效率非常低大数据量下的IO性能较低
-
基于fork创建子进程内存产生额外消耗
-
宕机带来的数据丢失风险
解决思路: 不写全数据,仅记录部分数据改记录数据为记录操作过程对所有操作均进行记录,排除丢失数据的风险
AOF概念
AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的。与RDB相比可以简单描述为改记录数据为记录数据产生的过程,AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式
AOF写数据三种策略(appendfsync)
-
always(每次)
- 每次写入操作均同步到AOF文件中,数据零误差,性能较低
-
everysec(每秒)
- 每秒将缓冲区中的指令同步到AOF文件中,数据准确性较高,性能较高在系统突然宕机的情况下丢失1秒内的数据
-
no(系统控制)
- 由操作系统控制每次同步到AOF文件的周期,整体过程不可控
AOF开启
配置 appendonly 为 yes 开启AOP持久化,默认是关闭状态
配置 appendfsync a lways | everysec |no AOP写数据策略
AOF重写方式
手动重写
bgrewriteaof 拆开 bg re write aof
自动重写
auto-aof-rewrite-min-size size
auto-aof- rewrite-percentage percentage
重写的工作原理
RDB 与 AOF区别
RDB与AOF 的选择
- 对数据非常敏感,建议使用默认的AOF持款化方案
- AOF持久化策略使用everysecond,每秒钟fsync-次。 该策略redis仍可以保持很好的处理性能,当出现问题时,最多丢失0- 1秒内的数据。
- 注意:由于AOF文件存储体积较大,且恢复速度较慢
- 数据呈现阶段有效性,建议使用RDB持久化方案
- 数据可以良好的做到阶段内无丢失(该阶段是开发者或运维人员手工维护的), 且恢复速度较快,阶段点数据恢复通常采用RDB方案
- 注意:利用RDB实现紧凑的数据持久化会使Redis降的很低
- 综合比对
- RDB与AOF的选择实际上是在做-种权衡,每种都有利有弊
- 如不能承受数分钟以内的数据丢失,对业务数据非常敏感,选用AOF
- 如能承受数分钟以内的数据失,且追求大数据集的恢复速度,选用RDB
- 灾难恢复选用RDB
- 双保险策略,同时开启RDB和AOF,重启后,Redis优先使用AOF来恢复数据,降低丢失数据的量
Redis 事务
什么是事务
Redis执行指令过程中,多条连续执行的指令被干扰,打断,插队
redis事务就是一个命令执行的队列, 将一系列预定义命令包装成一个整体 (一个队列) 。
当执行时,一次性按照添加顺序依次执行,中间不会被打断或者干扰。
一个队列中,一次性、顺序性、排他性的执行一列命令
事务的工作流程
没有添加事务的普通操作 服务器接收指令---》没有开启事务---》识别命令---》普通命令---》执行命令----》返回执行结果
添加了事务的操作 服务器接收指令---》开启事务---》识别命令----》MULTI---》创建队列---》返回ok结果 ----》识别普通命令 ---》加入创建好的队列----》返回QUEUED结果
如果识别到 EXEC -->执行事务 按顺序执行在队列中记录好的命令--->返回执行结果
如果是识别到 DISCARO --> 销毁队列 --->返回ok
Redis删除策略
过期数据
- Redis是一 种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态
- XX :具有时效性的数据
- -1 :永久有效的数据
- -2.:已经过期的数据或被删除的数据或未定义的数据
数据删除策略
时效性数据的存储结构
1.定时删除
- 创建一个定时器, 当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作
- 优点:节约内存,到时就删除,快速释放掉不必要的内存占用
- 缺点: CPU压力很大,无论CPU此时负载量多高,均占用CPU,会影响redis服务 器响应时间和指令鰻
总结:用处理器性能换取存储空间
2.惰性删除
-
数据到达过期时间,不做处理。等下次访问该数据时
- 如果未过期,返回数据
- 发现已过期,删除,返回不存在
- 每次访问之前都会执行expirelfNeeded()函数方法
-
优点:节约CPU性能,发现必须删除的时候才删除
-
缺点:内存压力很大,出现长期占用内存的数据
总结:存储空间换取处理器性能
3.定期删除
周期性轮询redis库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度
特点1: CPU性能占用设置有峰值,检测频度可自定义设置
特点2:内存压力不是很大,长期占用内存的冷数据会被持续清理
总结:周期性抽查存储空间(随机抽查,重点抽查)
逐出算法
-
检测易失数据(可能会过期的数据集server.db[i].expires )
- ①volatile-lru:挑选最近最少使用的数据淘汰
- ②volatile-lfu:挑选最近使用次数最少的数据淘汰
- ③volatile-ttl:挑选将要过期的数据淘汰
- ④volatile-random:任意选择数据淘汰
-
检测全库数据(所有数据集server.db[i].dict )
- ⑤allkeys-lru: 挑选最近最少使用的数据淘汰
- ⑥allkeys-lfu: 挑选最近使用次数最少的数据淘汰
- ⑦allkeys-random: 任意选择数据淘汰
-
放弃数据驱逐
- ⑧no-enviction (驱逐) :禁止驱逐数据(redis4.0中默认策略) ,会引发错误OOM (OutOf Memory)
数据删除策略的目标
在内存占用与CPU占用之间寻找一种平衡, 顾此失彼都会造成整体redis性能的下降,甚至引|发服务器宕机或 内存泄露
分布式锁框架-Redisson
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。Redisson底层采用的是Netty 框架。支持Redis 2.8以上版本,支持Java1.6+以上版本
主从复制
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。
好处:
1、读写分离,性能拓展
2、容灾快速恢复