Redis学习总结

1、Redis是什么

Redis是一个数据库,不过与传统数据库不同的是Redis的数据库是存在内存中,所以读写速度非常快,因此 Redis被广泛应用于缓存方向。

Redis也经常用来做分布式锁,Redis提供了多种数据类型来支持不同的业务场景。除此之外,Redis 支持事务持久化、LUA脚本、LRU驱动事件、多种集群方案。

2、Redis的数据结构

Redis支持五种数据结构:string字符串+hash哈希+list列表+set集合+Zset有序集合

2.1 string

String类型是二进制安全的,意思是 redis 的 string 可以包含任何数据。如数字,字符串,jpg图片或者序列化的对象。

1.缓存:经典使用场景,把常用信息,字符串,图片或者视频等信息放到redis中,redis作为缓存层,mysql做持久化层,降低mysql的读写压力。

2.计数器:redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源。

特点:

  • 获取字符串长度的复杂度为O(1)。
  • 杜绝缓冲区溢出。
  • 减少修改字符串长度时所需要的内存重分配次数。
  • 二进制安全。
  • 兼容部分C字符串函数。
2.2 list

当有一个列表键包含了数量比较多的元素,又或者列表中包含的元素都是比较长的字符串时,Redis就会使用链表作为列表建的底层实现。

例如:粉丝列表, 消息列表等功能都可以用Redis的 list 结构来实现

节点底层结构
typedef struct listNode {
	struct listNode *prev;  前置节点
	struct listNode *next;  后置节点
	void *value; 节点值
}listNode;

list底层结构
typedef struct list {
 
listNode *head;   表头节点
listNode *tail;    表尾节点
unsigned long len;// 链表所包含的节点数量
void *(*dup)(void *ptr);   // 节点值复制函数
void (*free)(void *ptr);    // 节点值是放过函数
int*match)(void *ptr, void *key); // 节点值对比函数
} list;

特点:

  • 链表被广泛用于实现Redis的各种功能,比如列表建、发布与订阅、慢查询、监视器等。
  • 每个链表节点由一个listNode结构来表示,每个节点都有一个指向前置节点和后置节点的指针,所以Redis的链表实现是双端链表
  • 每个链表使用一个list结构表示,这个结构带有表头节点指针、表尾节点指针,以及链表长度等信息。
  • 因为链表表头的前置节点和表尾节点的后置节点都指向NULL,所以Redis的链表实现是无环链表
  • 通过为链表设置不同的类型特定函数,Redis的链表可以用于保存各种不同类型的值。
2.3 hash

底层是哈希表,键值对;Redis的哈希表使用链地址法来解决键冲突,每个哈希表节点都有一个next指针,多个哈希表节点可以用这个单向链表连接起来。

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

2.4 set

不允许有重复的元素,集合中的元素是无序的,不能通过索引下标获取元素,支持集合间的操作,可以取多个集合取交集、并集、差集。

标签(tag),给用户添加标签,或者用户给消息添加标签,这样有同一标签或者类似标签的可以给推荐关注的事或者关注的人。

2.5 Zset

有序集合中的元素是可以排序的,它给每个元素设置一个分数,作为排序的依据。有序集合中的元素不可以重复,但是score 分数 可以重复。

特点:

  • 跳跃表是有序集合的底层实现之一。

  • Redis的跳跃表实现由zskiplist和zskiplistNode两个结构组成,其中zskiplist用于保存跳跃表信息(比如表头节点、表尾节点、长度),而zskiplistNode则用于表示跳跃表节点。

  • 每个跳跃表节点的层高都是1至32之间的随机数。层的数量越多,访问其他节点的速度越快。

  • 跳表是一种实现起来很简单,单层多指针的链表,它查找效率很高,堪比优化过的二叉平衡树。

  • 跳跃表以空间换时间的方式提升了查找速度。

  • Redis有序集合在节点元素较大或者元素数量较多时使用跳跃表实现。

3、Redis的特点:

高性能:假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据存在缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。

操作缓存就是直接操作内存,所以速度相当快。如果数据库中的对应数据改变的之后,可以同步改变缓存中相应的数据。

高并发:直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。

Redis采用单线程+IO多路复用

Redis的线程模型:

  • Redis内部使用文件事件处理器 file event handler,这个文件事件处理器是单线程的,所以 Redis才叫做单线程的模型;
  • 它采用 IO 多路复用机制同时监听多个 socket,根据 socket 上的事件来选择对应的事件处理器进行处理。I/O多路复用程序负责监听多个 套接字, 并向文件事件分派器传送那些产生了事件的套接字。

为什么采用单线程而不是多线程:

因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽,单线程比多线程更容易实现,因此采用单线程。

单线程Redis快主要是有三个原因:

  • Redis的全部操作都是纯内存的操作;
  • Redis采用单线程,有效避免了频繁的上下文切换;
  • 采用了非阻塞I/O多路复用机制。

4、Redis事务

Redis 事务特性:

  • 单独的隔离操作:所有命令会序列号,按顺序执行;事务执行过程中,不会被其他客户端发送的命令请求打断。
  • 没有隔离级别:队列中命令在没有提交之前都不会被执行。
  • 不保证原子性:事务中一条命令执行失败,其后的命令仍然被执行,没有回滚。

5、持久化操作:RDB+AOF

通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。

5.1 RDB为快照持久化:

在指定时间间隔内把内存中数据集快照写入磁盘;创建快照得到存储在内存里面的数据在某个时间点上的副本。

执行过程:

Redis单独创建一个子进程来进行持久化,将当前父进程的数据库数据复制到子进程的内存中,子进程把数据写入到一个临时文件中等待持久化结束再使用临时文件替换上次持久化的文件,保证数据的完整性和一致性。

主进程不进行IO操作,确保了高性能,适用于大规模的数据恢复且对数据的完整性不敏感情况,节省磁盘空间。

缺点:
①最后一次持久化后的数据可能丢失(时间间隔内服务器挂掉)。
②写时复制在数据量大时,影响性能。

5.2 AOF(append-only file)持久化

开启AOF持久化后每执行一条会更改Redis中的数据的命令(写操作),Redis就会将该命令写入硬盘中的AOF文件。

同步频率设置:让Redis每秒同步一次AOF文件,Redis性能几乎没受到任何影响。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。

当硬盘忙于执行写入操作的时候,Redis还会优雅的放慢自己的速度以便适应硬盘的最大写入速度;恢复:重启Redis会重新加载AOF中内容 。

特点: 实时性更好;丢失数据概率更低;(数据+操作)占用更多空间,备份速度慢。

AOF重写

AOF重写可以产生一个新的AOF文件,这个新的AOF文件和原有的AOF文件所保存的数据库状态一样但体积更小

通过读取数据库中的键值对来实现的(set k1 v1; set k2 v2)==(set k1 v1 k2 v2)

  • 会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新AOF文件期间,记录服务器执行的所有写命令。
  • 当子进程完成创建新AOF文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新AOF文件的末尾,使得新旧两个AOF文件所保存的数据库状态一致。
  • 最后,服务器用新的AOF文件替换旧的 AOF文件,以此来完成AOF文件重写操作。

6、主从复制:

在这里插入图片描述
读写分离,性能扩展;容灾快速恢复;一主多从。

主从复制原理:

  • 从服务器连接上主服务器后,从服务器向主服务器发送进行数据同步消息(从服务器发起)
  • 主服务器接收到以后,把主服务器数据进行持久化到rdb文件,把rdb文件发送到从服务器。从服务器进行文件读取完成主从复制。
  • 每次主服务器进行写操作之后,和从服务器进行数据同步(主服务器发起);增量复制/全量复制(重新连接都是全)

7、Redis应用问题

7.1 缓存穿透

应用服务器压力变大,查询一个一定不存在的数据,由于缓存不命中,接着查询数据库也无法查询出结果,因此也不会写入到缓存中,这将会导致每个查询都会去请求数据库,造成缓存穿透。

出现原因:出现很多非正常访问;Redis查询不到数据库;一般黑客攻击。

解决方法:

  • 对空值做缓存:设置空结果的过期时间很短
  • 设置可访问的名单(白名单):bitmaps类型定义白名单;存在才进行访问,不存在拦截;
  • 采用布隆过滤器:二进制向量(位图)和一系列随机映射函数(哈希函数)空间效率和查询时间较优;但误识别率和删除困难
  • 实时监控:命中率减低,排查对象;设置黑名单。

7.2 缓存击穿

数据库访问压力瞬时增大;Redis正常,没有大量key过期;
原因:Redis某个key过期,大量访问使用这个key;热门访问的key

解决方法:

  • 预先设置热门数据:加大key时长;
  • 实时调制:监控状态,现场设置;
  • 使用锁:

7.3 缓存雪崩
数据库压力变大,服务器崩溃。

原因:极少时间内,大量key集中过期;后面的请求都会落到数据库上,造成数据库短时间
内承受大量请求而崩掉。

解决方法:

  • 构建多级缓存架构:
  • 使用锁或队列:不适应高并发
  • 设置过期标志更新缓存:
  • 缓存失效时间分散:随机数生成失效时间
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值