当前位置: 首页 > >

Redis知识点本文就够

发布时间:



本文目录
一、 Redis数据结构(1)String 字符串(2)Hash 哈希(3)List链表(4)Set集合(5)Zset有序集合
二、 Redis单线程模型为啥这么快?(一)基于内存操作(二)C语言实现(三)简单的数据结构(四)I/O多路复用模型(五)单线程模型
三、持久化之RDB与AOF(一)RDB(二)AOF(三)RDB和AOF对比
四、 主从复制与故障转移(一)数据复制的意义(二)Redis注册复制原理(三)故障转移
五、 高可用与 Sentinel 哨兵(一)sentinel的功能
六、分布式缓存与 Redis Cluster七、缓存击穿(缓存穿透)、缓存雪崩(一) 缓存击穿(缓存穿透)(二)缓存雪崩
八、Redis热点Key九、布隆过滤十、Redis内存管理机制(一)最大内存限制(二)内存回收策略(1)删除过期键对象(2)内存溢出控制策略




一、 Redis数据结构
(1)String 字符串

使用场景:


1.缓存: 经典使用场景,把常用信息,字符串,图片或者视频等信息放到redis中,redis作为缓存层,mysql做持久化层,降低mysql的读写压力。
2.计数器:redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源。
3.session:常见方案spring session + redis实现session共享,


(2)Hash 哈希

使用场景:


1.缓存: 能直观,相比string更节省空间,的维护缓存信息,如用户信息,视频信息等。


(3)List链表

使用场景:


1.timeline:例如微博的时间轴,有人发布微博,用lpush加入时间轴,展示新的列表信息


(4)Set集合

使用场景:


1.标签(tag),给用户添加标签,或者用户给消息添加标签,这样有同一标签或者类似标签的可以给推荐关注的事或者关注的人。
2.点赞,或点踩,收藏等,可以放到set中实现


(5)Zset有序集合

使用场景:


1.排行榜:有序集合经典使用场景。例如小说视频等网站需要对用户上传的小说视频做排行榜,榜单可以按照用户关注数,更新时间,字数等打分,做排行。


二、 Redis单线程模型为啥这么快?
(一)基于内存操作

Redis将所有需要存储的数据都存放在内存中,基于内存的随机访问速度是磁盘的10万倍左右,即使是SSD也遥不可及,这是Redis操作快速的重要物理基础。


(二)C语言实现

相同逻辑下的C语言程序,执行效率要比其他语言的高很多。C语言与当前主流的操作系统之间有着独特的关系,抛开开发难度来看,执行速度还是蛮快的。


(三)简单的数据结构

内存数据库的另一个优点是,基于内存的数据结构要比基于硬盘的数据结构更加简单,对数据的操作也更加简单,因此Redis可以做很多事情,内部复杂性很小。Redis占用的内存空间也是比较少。


(四)I/O多路复用模型

单个线程通过记录跟踪每一个Sock(I/O流)的状态来同时管理多个I/O流。主要有select, poll, epoll三种实现方式。
1、select poll每次循环调用时,都需要将描述符和文件拷贝到内核空间;epoll 只需要拷贝一次;
2、select每次返回后,都需要遍历所有的描述文件才能找到就绪的,时间复杂度为O(n),而epoll则需要O(1);
3、poll比select的改进,就是使用链表来保存fd,使能监听的数量远远大于1024


(五)单线程模型

避免了多线程的启动、销毁、上下文切换、加锁、解锁等消耗资源的操作。单线程简单,不仅能避免上下文切换这种非常消耗资源的操作,而且可以避免死锁的情况。大大提升CPU的利用率。如果是多核服务器,可以通过启动多个Redis实例来利用多个CPU。


三、持久化之RDB与AOF

Redis 是一种基于内存的数据库,一旦断电、*簦琑edis 中的数据将不复存在。Redis 提供了 RDB 和 AOF 两个持久化的方式。当 Redis 实例*羰保梢允褂靡殉志没氖荩ㄎ募├椿乖诖媸菁


(一)RDB

这种持久化方式是将当前Redis内存中的数据生成 快照(Snapshot) 文件保存到硬盘,简单粗暴。RDB也是Redis默认开启的持久化方式。
1、 触发持久化
save
在之前已经废弃的 save 命令来实现RDB持久化数据,save 命令持久化时会一直阻塞,直到持久化完成。数据量越大,持久化过程带来的阻塞时间就越长。
bgsave
现在可以使用 bgsave 命令来代替 save。bg就是background,使用 bgsave 方式RDB持久化时,Redis工作进程会 fork 一个子进程,该子进程专门来负责耗时的RDB持久化,而工作进程会继续工作,阻塞时间只发生在短暂的 fork 阶段。
除了主动触发命令外,Redis还是提供了自动触发RDB持久化命令 bgsave ,该命令表示在seconds秒内,Redis内存数据修改的次数达到changes次时,将触发RDB持久化。比如 bgsave 7200 10 表示在2个小时内,数据被更改10次时将自动触发RDB持久化。
(注意changes计数并不包含查询语句,当然被操作的key一定存在,否则也不会进行计数)
2、 数据快照存储
首先,工作目录默认为当前Redis目录,那么持久化的RDB数据快照将存储在该目录,可通过 dir ./ 参数进行修改。生成的数据存储快照名称默认为 dump.rdb ,可通过 dbfilename dump.rdb 参数进行修改。RDB持久化先生存一个临时快照,待数据持久化完成,这个临时快照会替换原快照,以防持久化过程出现问题。
RDB存储快照默认是使用LZF算法压缩功能,压缩后的文件体积将大大减少。压缩文件但并不是十全十美,RDB快照压缩时也会消耗CPU,数据量越大,消耗CPU资源就越多,但官网还是极力推荐我们开始此功能。
RDB持久化时可能出现权限问题、存储空间不够用等问题,Redis 默认开启stop-writes-on-bgsave-error yes 参数,意味着出现 error时,Redis将停止向快照文件写入数据。
在Redis保存/恢复数据时,并不是一股脑进行保存/恢复,默认会对RDB快照文件进行检查,性能会受到影响(大约10%),因此可以禁用它以获得最大的性能。(推荐开启)


(二)AOF

这种持久化方式是通过保存写命令来记录操作日志,在数据恢复时,重新执行已记录的写命令,来达到数据恢复。
1、 AOF原理
默认情况下,AOF是关闭的,可以通过修改 appendonly no 为 appendonly yes 来开启 AOF 持久化。内存的Output的带宽远大于磁盘Input的带宽,如果内存瞬时将大量的数据写入磁盘,必然发生IO堵塞,对于单线程工作的Redis也将会在性能上大打折扣。所以所有的写命令并不会直接写入AOF文件,而是先将写命令存储至AOF Buffer缓冲区,最后在同步至AOF文件。
生成的AOF文件名,默认为 appendonly.aof ,可以修改 appendfilename “appendonly.aof” 参数来更改生成的AOF文件名。
从缓冲区同步至磁盘,Redis提供了三种同步方式:
always: 写命令被追加到AOF缓存后,调用系统fsync函数将缓冲区的数据同步至磁盘,最后返回
everysec: 写命令被追加到AOF缓存后,调用系统write函数,在write函数执行完成,然后返回,会触发系统将对缓冲区的数据进行同步至磁盘
no: 写命令被追加到AOF缓存后,调用系统write函数,然后返回,后续的同步由系统负责
其中 everysec 不仅是默认的方式,也是推荐的方式。
2、 AOF重写机制
AOF持久化文件存储的是Redis写命令,这比仅仅是数据的存储文件要大了很多。在AOF重写机制中,首先遍历数据库,如果数据库为空库,则跳过该库。对于非空的数据库,则遍历所有的key,如果key过期则跳过该key,如果key有过期时间则设置key的过期时间。
AOF的重写机制并不是随机触发的,默认是当前写入AOF文件大小较上次重写后文件大小增长了 100% 时就触发重写机制。比如上次重写后的文件大小是1G,经过一段时间,AOF文件体积增长了 1G ,那么增长率就是 100% ,就会触发AOF重写。可以通过设置 auto-aof-rewrite-percentage 100 来调节文件增长率的触发阈值。
如果AOF的文件较少,不足以影响太大性能,所以没必要重写AOF文件。可以通过 auto-aof-rewrite-min-size 64mb 来设置AOF文件重写的最小阈值。
aof-load-truncated yes 参数表示,在Redis恢复数据时,最后一条命令可能不完整,开启则表示忽略最后一条不完整的命令。


(三)RDB和AOF对比

RDB开始压缩后,生成一个体量更小、更紧凑的二进制文件,占有空间小。RDB不仅有着较快的数据恢复能力,而且可以直接复制RDB文件至其他Redis实例进行回复数据,有着良好的容灾体验。RDB适用于定时复制、全量复制、快速恢复的场景,由于RDB文件生成时间长,数据有存储延迟,不适用于*实时持久化的场景。
AOF以追加命令的方式,持续的、*实时的写入文件(秒级别)。而且,在一定程度时,AOF不断的重写持久化文件,不断的优化。特别是在数据完整性上要比RDB好很多,例如,使用默认的数据同步策略,Redis在发生服务器断电等重大事件时,可能只丢失一秒钟的写入时间,或者在Redis进程本身发生错误但操作系统仍在正常运行时丢失一次写入时间。所以AOF比较适合对数据实时性和数据完整性要求比较高的场景。AOF相较于RDB,缺点是文件相对较大,而且恢复数据时因为要执行全部的写命令,所以数据恢复比较慢,特别在是在被依赖的应用系统高负载的情况下,较长时间的数据恢复,对后端系统是不可容忍的。
但AOF和RDB持久性可以同时启用,不会出现问题。如果在启动时启用了AOF,redis将加载AOF,即具有更好的持久性保证的文件。而且在较新的版本还支持混合模式。
RDB-AOF混合持久化
Redis从 4.0 开始支持RDB-AOF混合持久化,默认是关闭状态,可以通过 aof-use-rdb-preamble yes 开启。AOF文件在重写之后,将生成一份记录已有数据的RDB快照文件,再生成一份记录最*写命令的AOF文件,作为对RDB快照的补充。这样的混合持久化模式,将兼具RDB和AOF的双优特性。


四、 主从复制与故障转移
(一)数据复制的意义

1、读写分离,降低单节点的读写压力;
2、容灾转移,单机出现问题,从节点接替。


(二)Redis注册复制原理

首先,通过上述配置主从复制,从节点保存主节点的信息,然后建立 socket 连接。Redis的ping命令是用于客户端检测服务端是否正常运作或消息延时的一种命令,是一种心跳机制,在这里从节点就是客户端,主节点就是服务端。从节点发送ping命令至主节点,如果主节点正常运作则返回pong,这样才能表示双方网络通达。紧接着,如果主节点开启 requirepass foobared 参数(foobared 可以认为是安全校验密码),主节点会对从节点进行权限校验。密码正确后,才进行数据同步,最后不断的、陆陆续续的、持续复制后面的数据,实现这一持续复制数据的实现方式就是复制其操作命令。


(三)故障转移

对于单个节点而言,有可能出现故障(fail),为了保证该服务的可用性,需要使用其他冗余或备用节点来接替该节点工作,这种拯救方式就是 故障转移(Failover) 。
比如一个 一主两从 的高可用方案,主节点工作,从节点作备用:
如果主节点(master节点)出现故障,那么服务不可用,从节点(slave节点)也无法从master节点持续复制数据,如何实现故障转移呢?下面是基于客户端的实现。
1、客户端使用心跳机制,定时检测 master、slave节点活性,比如使用ping命令;
2、如果master节点在一定时间内无回复,则认为master节点此时不可用;
3、从slave节点中随机选择或选择一个ping-pong网络较好的一个节点晋升为master,比如6380节点;
4、6380节点和6381节点先与6379断开复制关系 slaveof no one;
5、然后以6380为master节点,6381为salve节点建立复制关系;
建立新的主从复制
6、通过心跳检测6379节点故障恢复后,作为salve节点与master节点建立主从复制关系;
屏幕快照 2019-02-16 下午4.10.30.png
7、故障转移完成。(其实到了第3步选取6380为主节点后,服务就可用了)
客户端为了高可用,也可以做成多节点,在Redis的master节点出现故障时,客户端多节点通过选举方式来产生新的master节点。从Redis 2.8 版本开始,新加入了 Redis Sentinel 来实现高可用。


五、 高可用与 Sentinel 哨兵

Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换。


(一)sentinel的功能

1.监控
Sentinel会不断地检查你的主服务器和从服务器是否运作正常。
2.提醒
当被监控的某个Redis服务器出现问题时,Sentinel可以通过API向管理员或者其他应用程序发送通知。
3.自动故障迁移
当一个主服务器不能正常工作时,Sentinel会开始一次自动故障迁移操作,它会将失效主服务器的其中一个从服务器升级为新的主服务器,并让失效主服务器的其他从服务器改为复制新的主服务器;当客户端试图连接失效的主服务器时,集群也会向客户端返回新主服务器的地址,使得集群可以使用新主服务器代替失效服务器。


六、分布式缓存与 Redis Cluster

redis最开始使用主从模式做集群,若master宕机需要手动配置slave转为master;后来为了高可用提出来哨兵模式,该模式下有一个哨兵监视master和slave,若master宕机可自动将slave转为master,但它也有一个问题,就是不能动态扩充;所以在3.x提出cluster集群模式。
Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。


七、缓存击穿(缓存穿透)、缓存雪崩
(一) 缓存击穿(缓存穿透)

缓存(Cache) 是分布式、高并发的场景下,为了保护后端数据库,降低数据库的压力,引入的一种基于内存的数据访问机制,能加快数据的读取与写入,进而提高系统负载能力。


缓存击穿(缓存穿透) 是访问不存在缓存中的数据,进而直接访问数据库。
缓存击穿 和 缓存穿透 更为详细的分类:

在缓存穿透这种情形下,如果缓存和数据库都没有需要被访问的数据,那么访问缓存时没有数据则直接返回空,避免重复访问数据库,造成不必要的后端数据库压力。
解决方案
1.缓存空值: 如果第一次访问一个不存在的数据,那么将此key与value为空值的数据缓存起来,下次再有对应的key访问时,缓存直接返回空值,通常要设置key的过期时间,再次访问时更新过期时间;
2.布隆过滤: 类似散列集合(hash set),判断key是否在这个集合中。实现机制在于比特位,一个key对应一个比特位,并且存储一个标识,如果key有对应的比特位,并且标识位表示存在,则表示有对应的数据。比如使用Redis 的 Bitmap实现。


(二)缓存雪崩

大量的缓存击穿意味着大量的请求怼在数据库上,轻者造成数据库响应巨慢,严重者造成数据库宕机。比如缓存内的数据集体定时刷新、服务器*舻取
解决方案
1、降低缓存刷新频率;
2、部分缓存刷新,刷新数据时按照一定规则分组刷新;
3、设置key永远不过期,如果需要刷新数据,则定时刷新;
4、分片缓存,在分布式缓存下,将需要缓存的数据 散列 分布到多个节点,尽量将热点数据均匀分布到多节点。


八、Redis热点Key

在一定时间内,被频繁访问的key称为 热点key 。比如突发性新闻,微博上常见的热搜新闻,引起千千万万人短时间内浏览;在线商城大促活动,消费者比较关注的商品突然降价,引起成千上万消费者点击、购买。热点key会导致流量过于集中,缓存服务器的压力骤然上升,如果超出物理机器的承载能力,则缓存不可用,进而可能诱发缓存击穿、缓存雪崩的问题。
解决方案
1、 读写分离
通过将数据的写入与读取分散去各个节点,通过数据复制到达各个节点数据一致性的目的。在写少的情形下,master节点写入数据,在读取请求压力大的情形下,配置多个slave节点,数据横向同步(*私峁梗=岷蟁edis Sentinel (或其他高可用技术)实现缓存节点的高可用。
2、 阿里云云数据库 Redis 版解决方案
在热点 Key 的处理上主要分为写入跟读取两种形式,在数据写入过程当 SLB 收到数据 key1 并将其通过某一个 Proxy 写入一个 Redis,完成数据的写入。假若经过后端热点模块计算发现 key1 成为热点 key 后, Proxy 会将该热点进行缓存,当下次客户端再进行访问 key1 时,可以不经 Redis。最后由于 Proxy 是可以水*扩充的,因此可以任意增强热点数据的访问能力。
3、 热点key不过期
如果key存在,那么不要设置key过期时间,如果key对应的数据不可用(比如删除了),那么从缓存中删除key。从请求来说,如果在缓存找到对应的key,表明该key及其value就是用户需要的数据。如果缓存中不存在对应的key,表明无对应的数据,返回空值。比如微博发来爆料某明星文章,短时间内访问量直接上升,如果key不过期,那么请求永远命中缓存。只有当文章被删除的时候,才从缓存中删除对应的key,如果此时还有请求访问,在缓存中查无数据时,直接返回空值,表明文章被删除。当然也可以更新key对应的value值,返回想要表达的value。


九、布隆过滤

布隆过滤器是一个神奇的数据结构,可以用来判断一个元素是否在一个集合中。很常用的一个功能是用来去重。布隆过滤器本质是一个位数组,位数组就是数组的每个元素都只占用 1 bit 。每个元素只能是 0 或者 1。
布隆过滤器除了一个位数组,还有 K 个哈希函数。当一个元素加入布隆过滤器中的时候,会进行如下操作:
1、使用 K 个哈希函数对元素值进行 K 次计算,得到 K 个哈希值。
2、根据得到的哈希值,在位数组中把对应下标的值置为 1。
3、当要判断一个值是否在布隆过滤器中,对元素再次进行哈希计算,得到值之后判断位数组中的每个元素是否都为 1,如果值都为 1,那么说明这个值在布隆过滤器中,如果存在一个值不为 1,说明该元素不在布隆过滤器中。


布隆过滤器说某个元素在,可能会被误判。布隆过滤器说某个元素不在,那么一定不在。
十、Redis内存管理机制
(一)最大内存限制

Redis使用 maxmemory 参数限制最大可用内存,默认值为0,表示无限制。
1、用于缓存场景,当超出内存上限 maxmemory 时使用 LRU 等删除策略释放空间。
2、防止所用内存超过服务器物理内存。因为 Redis 默认情况下是会尽可能多使用服务器的内存,可能会出现服务器内存不足,导致 Redis 进程被杀死。


(二)内存回收策略
(1)删除过期键对象

采用惰性删除和定时任务删除机制实现过期键的内存回收。
惰性删除是指当客户端操作带有超时属性的键时,会检查是否超过键的过期时间,然后会同步或者异步执行删除操作并返回键已经过期。这样可以节省 CPU成本考虑,不需要单独维护过期时间链表来处理过期键的删除。
Redis 内部维护一个定时任务,默认每秒运行10次(通过配置控制)。定时任务中删除过期键逻辑采用了自适应算法,根据键的过期比例、使用快慢两种速率模式回收键。


(2)内存溢出控制策略

当内存达到 maxmemory 时触发内存溢出控制策略,强制删除选择出来的键值对象。


每次Redis执行命令时如果设置了maxmemory参数,都会尝试执行回收内存操作。当Redis一直工作在内存溢出(used_memory>maxmemory)的状态下且设置非 noeviction 策略时,会频繁地触发回收内存的操作,影响Redis 服务器的性能。



友情链接: hackchn文档网 营销文档网 爱linux网 爱行业网 时尚网