透彻理解redis

Posted 一支会记忆的笔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了透彻理解redis相关的知识,希望对你有一定的参考价值。

                       

 前言......

           

 

Redis 作为一个开源的,高级的键值存储和一个适用的解决方案,已经越来越在构建 「高性能」、「可扩展」 的 Web 应用上发挥着举足轻重的作用。

当今互联网技术架构中 Redis 已然成为了应用得最广泛的中间件之一,它也是中高级后端工程 技术面试 中面试官最喜欢问的工程技能之一,
不仅仅要求着我们对 基本的使用 进行掌握,更要深层次地理解 Redis 内部实现 的细节原理。

什么是 Redis ?

Redis (Remote Dictionary Server) 是一个使用 C 语言 编写的,开源的 (BSD许可) 高性能 非关系型 (NoSQL) 的 键值对数据库。

简单提一下 Redis 数据结构

Redis 可以存储 键 和 不同类型数据结构值 之间的映射关系。键的类型只能是字符串,而值除了支持最 基础的五种数据类型 外,还支持一些 高级数据类型

                                       

 

 Redis 小总结

与传统数据库不同的是 Redis 的数据是 存在内存 中的,所以 读写速度 非常 快,因此 Redis 被广泛应用于 缓存 方向,每秒可以处理超过 10 万次读写操作,
是已知性能最快的 Key-Value 数据库。另外,Redis 也经常用来做 分布式锁。除此之外,Redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。

Redis 应用场景

  1. 缓存

  2. 共享Session

  3. 消息队列系统

  4. 分布式锁

Redis 优缺点

优点

读写性能优异, Redis能读的速度是 110000 次/s,写的速度是 81000 次/s。
支持数据持久化,支持 AOF 和 RDB 两种持久化方式。
支持事务,Redis 的所有操作都是原子性的,同时 Redis 还支持对几个操作合并后的原子性执行。
数据结构丰富,除了支持 string 类型的 value 外还支持 hash、set、zset、list 等数据结构。
支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。

缺点

数据库量受到物理内存的限制,不能用作海量数据的高性能读写,因此 Redis 适合的场景主要局限在较小数据量的高性能操作和运算上。
Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的 IP 才能恢复。
主机宕机,宕机前有部分数据未能及时同步到从机,切换 IP 后还会引入数据不一致的问题,降低了 系统的可用性。
Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费

为什么要用缓存?为什么使用 Redis?

提一下现在 Web 应用的现状

在日常的 Web 应用对数据库的访问中,读操作的次数远超写操作,比例大概在 1:9 到 3:7,所以需要读的可能性是比写的可能大得多的。

频繁读写数据
当我们使用 SQL 语句去数据库进行读写操作时,数据库就会 去磁盘把对应的数据索引取回来,这是一个相对较慢的过程。 直接操作数据库不安全

使用 Redis or 使用缓存带来的优势

如果我们把数据放在 Redis 中,也就是直接放在内存之中,让服务端直接去读取内存中的数据,那么这样 速度 明显就会快上不少 (高性能),并且会 极大减小数据库的压力 (特别是在高并发情况下)。

记得是 两个角度 啊.. 高性能 和 高并发..

使用缓存会出现什么问题?

一般来说有如下几个问题,回答思路遵照 是什么 → 为什么 → 怎么解决

缓存雪崩问题;
缓存穿透问题;
缓存和数据库双写一致性问题;

缓存雪崩问题

    同一时间大量的缓存失效导致同一时刻大量的请求全部访问数据库 造成宕机  

 

 

另外对于 "Redis 挂掉了,请求全部走数据库" 这样的情况,我们还可以有如下的思路:

  • 事发前:实现 Redis 的高可用(主从架构 + Sentinel 或者 Redis Cluster),尽量避免 Redis 挂掉这种情况发生。
  • 事发中:万一 Redis 真的挂了,我们可以设置本地缓存(ehcache) + 限流(hystrix),尽量避免我们的数据库被干掉(起码能保证我们的服务还是能正常工作的)
  • 事发后:Redis 持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。

缓存穿透问题

    当大量请求访问一个根本就不存在的数据如id为负数  此时就会直接访问数据库 造成数据库压力很大 导致宕机

 

 

缓存击穿问题

    就是说某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在缓存中失效的瞬间  大量用户同时访问一个数据时  导致大量请求直接走数据库  造成数据库服务宕机 

 

 缓存与数据库双写一致问题

 

 

双写一致性上图还是稍微粗糙了些,你还需要知道两种方案 (先操作数据库和先操作缓存) 分别都有什么优势和对应的问题,这里不作赘述,可以参考一下下方的文章,写得非常详细。

Redis 为什么早期版本选择单线程?

因为 Redis 是基于内存的操作,CPU 不是 Redis 的瓶颈,Redis 的瓶颈最有可能是 机器内存的大小 或者 网络带宽。既然单线程容易实现,而且 CPU 不会成为瓶颈,那就顺理成章地采用单线程的方案了。

简单总结一下

  1. 使用单线程模型能带来更好的 可维护性,方便开发和调试;
  2. 使用单线程模型也能 并发 的处理客户端的请求;(I/O 多路复用机制)
  3. Redis 服务中运行的绝大多数操作的 性能瓶颈都不是 CPU

强烈推荐 各位亲看一下这篇文章:

Redis 为什么这么快?

简单总结:

  1. 纯内存操作:读取不需要进行磁盘 I/O,所以比传统数据库要快上不少;(但不要有误区说磁盘就一定慢,例如 Kafka 就是使用磁盘顺序读取但仍然较快)
  2. 单线程,无锁竞争:这保证了没有线程的上下文切换,不会因为多线程的一些操作而降低性能;
  3. 多路 I/O 复用模型,非阻塞 I/O:采用多路 I/O 复用技术可以让单个线程高效的处理多个网络连接请求(尽量减少网络 IO 的时间消耗);
  4. 高效的数据结构,加上底层做了大量优化:Redis 对于底层的数据结构和内存占用做了大量的优化,例如不同长度的字符串使用不同的结构体表示,HyperLogLog 的密集型存储结构等等..

 

 

Redis的持久化

Redis持久化

 

 

 什么是持久化

Redis 的数据 全部存储 在 内存 中,如果 突然宕机,数据就会全部丢失,因此必须有一套机制来保证 Redis 的数据不会因为故障而丢失,
这种机制就是 Redis 的 持久化机制,它会将内存中的数据库状态 保存到磁盘 中。

 Redis持久化的两种方式:

方式一:RDB 

      RDB       在指定的时间间隔内将内存中的数据集以快照的方式写入磁盘

          

快照不是很持久。如果运行 Redis 的计算机停止运行,电源线出现故障或者发生意外,则写入 Redis 的最新数据将丢失

 

 

 

 

方式二:AOF 

       AOF     以日志的形式记录数据写入到磁盘(文件追加的方式写入磁盘)

          

 

 

 RDB和AOF的区别:

 

RDB | 优点

  1. 只有一个文件 dump.rdb方便持久化
  2. 容灾性好,一个文件可以保存到安全的磁盘。
  3. 性能最大化fork 子进程来完成写操作,让主进程继续处理命令,所以使 IO 最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 Redis 的高性能
  4. 相对于数据集大时,比 AOF 的 启动效率 更高。

RDB | 缺点

  1. 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 Redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候;

AOF | 优点

  1. 数据安全,aof 持久化可以配置 appendfsync 属性,有 always每进行一次命令操作就记录到 aof 文件中一次。
  2. 通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。
  3. AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall)

AOF | 缺点

    1. AOF 文件比 RDB 文件大,且 恢复速度慢
    2. 数据集大 的时候,比 rdb 启动效率低

 

Redis的 集群

 

 Redis集群

主从同步的了解

主从复制,是指将一台 Redis 服务器的数据,复制到其他的 Redis 服务器。前者称为 主节点(master),后者称为 节点(slave)。且数据的复制是 单向 的,只能由主节点到从节点。Redis 主从复制支持 主从同步 和 从从同步 两种,后者是 Redis 后续版本新增的功能,以减轻主节点的同步负担。

主从复制主要的作用

  • 数据冗余 主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  • 故障恢复 当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复 (实际上是一种服务的冗余)
  • 负载均衡 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务 即写 Redis 数据时应用连接主节点,读 Redis 数据时应用连接从节点,分担服务器负载。尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量。
  • 高可用基石 除了上述作用以外,主从复制还是哨兵和集群能够实施的 基础,因此说主从复制是 Redis 高可用的基础。

实现原理:

 

 

 简化成三个阶段:准备阶段-----------数据同步阶段-------------命令传播阶段

 

Redis如何实现分布式锁

推荐阅读 之前的系列文章:
Redis(3)——分布式锁深入探究 -传送门

Redis过期健的删除策略

简单描述

先抛开 Redis 想一下几种可能的删除策略:

  1. 定时删除:在设置键的过期时间的同时,创建一个定时器 timer). 让定时器在键的过期时间来临时,立即执行对键的删除操作。
  2. 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。
  3. 定期删除:每隔一段时间程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。

在上述的三种策略中定时删除和定期删除属于不同时间粒度的 主动删除惰性删除属于 被动删除

三种策略都有各自的优缺点

  1. 定时删除对内存使用率有优势,但是对 CPU 不友好;
  2. 惰性删除对内存不友好,如果某些键值对一直不被使用,那么会造成一定量的内存浪费;
  3. 定期删除是定时删除和惰性删除的折中。

Redis 中的实现

Reids 采用的是 惰性删除和定时删除 的结合,一般来说可以借助最小堆来实现定时器,不过 Redis 的设计考虑到时间事件的有限种类和数量,使用了无序链表存储时间事件,这样如果在此基础上实现定时删除,就意味着 O(N) 遍历获取最近需要删除的数据

参考资料:

 

 

 

 

 

 

 

 

来源于---->传送门https://www.cnblogs.com/wmyskxz/p/12568926.html#_label4_0

 

以上是关于透彻理解redis的主要内容,如果未能解决你的问题,请参考以下文章

拾遗理解Javascript中的Arguments

透彻理解Ioc

手写RPC框架,理解更透彻,代码已上传Github!

(透彻理解)最精锐代码::堆的三种基本操作新建-插入-删除

程序员要透彻理解单例模式

看部电影,透透彻彻理解IoC(你没有理由再迷惑!)