redis详解认知深入


提示:以下是本篇文章正文内容,下面案例可供参考

一、Redis应用场景

计数器 :
可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量。

缓存 :
将热点数据放到内存中,设置内存的大使用量以及淘汰策略来保证缓存的命中率。

会话缓存 :
可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存 储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务 器,从而更容易实现高可用性以及可伸缩性。

全页缓存(FPC):
除基本的会话token之外,Redis还提供很简便的FPC平台。以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以 快速度加载你曾浏览过的页面。

查找表:
例如 DNS 记录就很适合使用 Redis 进行存储。查找表和缓存类似,也是利用了Redis 快速的查找特性。但是查找表的内容不能失效,而缓存的内容可以失效, 因为缓存不作为可靠的数据来源。

消息队列(发布/订阅功能) :
List 是一个双向链表,可以通过 lpush 和 rpop 写入和读取消息。不过有好用的Kafka、RabbitMQ 等消息中间件。

分布式锁实现:
在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可 以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的RedLock 分布式锁实现。

其它 :
Set 可以实现交集、并集等操作,从而实现共同好友等功能。ZSet 可以实现有序性操作,从而实现排行榜等功能。
string——适合简单的k-v存储,类似于memcached的存储结构,短信验证码,配置信息等,就用这种类型来存储。
hash——一般key为ID或者唯一标示,value对应的就是详情了。如商品详情, 个人信息详情,新闻详情等。
list——因为list是有序的,比较适合存储一些有序且数据相对固定的数据。如省 市区表、字典表等。因为list是有序的,适合根据写入的时间来排序,如:消息队列等。
set——可以简单的理解为ID-List的模式,如微博中一个人有哪些好友,set 牛的地方在于,可以对两个set提供交集、并集、差集操作。例如:查找两个人 共同的好友等。
Sorted Set——是set的增强版本,增加了一个score参数,自动会根据score的 值进行排序。比较适合类似于top 10等不根据插入的时间来排序的数据。
如上所述,虽然Redis不像关系数据库那么复杂的数据结构,但是,也能适合很 多场景,比一般的缓存数据结构要多。了解每种数据结构适合的业务场景,不仅 有利于提升开发效率,也能有效利用Redis的性能。

二、Redis优势

Redis 是一个开源(BSD 许可)、基于内存、支持多种数据结构的存储系统,可以作为数据库、缓存和消息中间件。它支持的数据结构有字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等,除此之外还支持 bitmaps、hyperloglogs 和地理空间(geospatial )索引半径查询等功能。
它内置了复制(Replication)、LUA 脚本(Lua scripting)、LRU 驱动事件(LRU eviction)、事务(Transactions)和不同级别的磁盘持久化(persistence)功能,并通过 Redis 哨兵(哨兵)和集群(Cluster)保证缓存的高可用性(High availability)。

具有以下好处:
读取速度快,因为数据存在内存中,所以数据获取快,提升读取性能,同时也减轻mysql 的读取压力;
支持多种数据结构,包括字符串、列表、集合、有序集合、哈希等;
支持事务,且操作遵守原子性,即对数据的操作要么都执行,要么都不支持;
还拥有其他丰富的功能,队列、主从复制、集群、数据持久化等功能。

三、Redis 单线程模型效率高的原因、线程模型

  1. C语言实现,效率高
  2. 基于内存操作,绝大部分请求是纯粹的内存操作,非常快速
  3. 基于非阻塞的IO复用模型机制(单线程io多路复用)
  4. 单线程的话就能避免多线程的频繁上下文切换问题,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁 操作,没有因为可能出现死锁而导致的性能消耗;
  5. 数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的

Redis 内部使用文件事件处理器 file event handler ,这个文件事件处理器是单线程的,所以Redis 才叫做单线程的模型。它采用IO多路复用机制同时监听多个socket,根据socket上的事件来选择对应的事件处理器进行处理。
多个socket可能会并发产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用程序会监听多个socket,会将socket产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。
文件事件处理器的结构包含4个部分:
1>多个 socket
2>IO 多路复用程序
3>文件事件分派器
4>事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
在这里插入图片描述

四、Memcache与Redis 区别

  • Redis 和 Memcache 都是将数据存放在内存中,都是内存数据库。不过 Memcache还可用于缓存其他东西,例如图片、视频等等。
  • Memcache 仅支持key-value结构的数据类型,Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,hash等数据结构的存储。
  • 虚拟内存:Redis 当物理内存用完时,可以将一些很久没用到的value 交换到磁盘
  • 分布式:设定 Memcache 集群,利用 magent 做一主多从; Redis 可以做一主多从。都可以一主多从
  • 存储数据安全– Memcache 挂掉后,数据没了; Redis 可以定期保存到磁盘(持久化机制)
  • Memcache 的单个value最大 1m , Redis 的单个value最大 512m 。
  • 灾难恢复– Memcache 挂掉后,数据不可恢复; Redis 数据丢失后可以通过 aof 恢复
  • Redis 原生就支持集群模式, Redis3.0 版本中,官方便能支持Cluster模式了,Memcached 没有原生的集群模式,需要依赖客户端来实现,然后往集群中分片写入数据。
  • Memcached 网络IO模型是多线程,非阻塞IO复用的网络模型,原型上接近于 nignx 。而 Redis使用单线程的IO复用模型,自己封装了一个简单的 AeEvent 事件处理框架,主要实现类epoll,kqueue 和 select ,更接近于Apache早期的模式。

五、Redis 主从架构

Redis 支持主从同步、从从同步。如果是第一次进行主从同步,主节点需要使用bgsave 命令,再将后续修改操作记录到内存的缓冲区,等 RDB 文件全部同步到复制节点,复制节点接受完成后将RDB 镜像记载到内存中。等加载完成后,复制节点通知主节点将复制期间修改的操作记录同步到复制节点,即可完成同步过程。
在这里插入图片描述
一个 master node 是可以配置多个 slave node 的;slave node 也可以连接其他的 slave node;
slave node 做复制的时候,不会 block master node 的正常工作,也不会 block 对自己的查询操作,它会用旧的数据集来提供服务;但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了;
slave node 主要用来进行横向扩容,做读写分离,扩容的 slave node 可以提高读的吞吐量。

在这里插入图片描述
1>当从库和主库建立MS关系后,会向主数据库发送SYNC命令
2>主库接收到SYNC命令后会开始在后台保存快照(RDB持久化过程),并将期间接收到的写命令存起来
3>当快照完成后,主Redis会将快照文件和所有缓存的写命令发送给从Redis
4>从Redis接收到后,会载入快照文件并且执行收到的缓存的命令
5>之后,主Redis每当接收到写命令时就会将命令发送从Redis,从而保证数据的一致

Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384 (2的14次方)个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽

六、Redis 持久化机制

RDB(默认) Redis DataBase 和 AOF 机制
RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保 存到硬盘中,对应产生的数据文件为dump.rdb。通过配置文件中的save参数来 定义快照的周期。

  • 优点:
  1. 只有一个文件 dump.rdb,方便持久化。
  2. 容灾性好,一个文件可以保存到安全的磁盘。
  3. 性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是IO最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能
  4. 相对于数据集较大时,比 AOF 的启动效率更高。
  • 缺点:
  1. 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发 生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候。

AOF(Append-only file)持久化方式是将Redis执行的每次写命令记录 到单独的日志文件中,当重启Redis会重新将持久化的日志中文件恢复数据。 当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复

  • 优点:
  1. 数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次命令操作就记录到 aof 文件中一次。
  2. 通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-checkaof 工具解决数据一致性问题。
  3. AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的 flushall)
  • 缺点:
  1. AOF 文件比 RDB 文件大,且恢复速度慢。
  2. 数据集较大的时候,比 rdb 启动效率低啊

如何选择?

  • 一般来说, 如果想达到足以媲美PostgreSQL的数据安全性,你应该 同时使用两种持久化功能。在这种情况下,当 Redis 重启的时候会优先载 入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集 要比RDB文件保存的数据集要完整。
  • 如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用RDB持久化。
  • 有很多用户都只使用AOF持久化,但并不推荐这种方式,因为定时生 成RDB快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据 集的速度也要比AOF恢复的速度要快,除此之外,使用RDB还可以避免 AOF程序的bug。
  • 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任 何持久化方式。

七、Redis 缓存刷新/清除策略

Redis中缓存的key过期,过期策略

  • 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。(贪心策略进行每秒扫十次,拿20个看是否过期,如果过期的超过1/4,删了之后再继续)
  • 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以 大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
  • 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到 优的平衡效果。
  • EXPIRE 设置key 的过期时间 PERSIST 设置key永久有效

内存淘汰策略

配置参数 maxmemory 来限制内存大小,超过该大小后进行淘汰
1.全局的键空间选择性移除

  • noeviction:当内存不足以容纳新写入数据时,新写入操作会报错
  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key
  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key

2.设置过期时间的键空间选择性移除

  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key
  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除

3.内存优化:存储尽可能使用散列表Hash,使用的内存比较小,尽可能的将数据模型数据模型抽象到一个散列表里面,像是用户对象的多个属性。

八、Redis事务

  • Redis 事务是不支持回滚的,不像 MySQL 的事务一样,要么都执行要么都不执行;
  • Redis 服务端在执行事务的过程中,不会被其他客户端发送来的命令请求打断。直到事务命令全部执行完毕才会执行其他客户端的命令。
  • Redis 的事务不支持回滚,但是执行的命令有语法错误,Redis 会执行失败,这些问题可以从程序层面捕获并解决。但是如果出现其他问题,则依然会继续执行余下的命令。这样做的原因是因为回滚需要增加很多工作,而不支持回滚则可以保持简单、快速的特性

九、Redis集群

  • Redis Sentinel
    体量较小时,选择 Redis Sentinel ,单主 Redis 足以支撑业务。
  • Redis Cluster
    Redis 官方提供的集群化方案,体量较大时,选择 Redis Cluster ,通过分片,使用更多内存。
  • Twemprox
    Twemprox 是 Twtter 开源的一个 Redis 和 Memcached 代理服务器,主要用于管理Redis 和Memcached 集群,减少与Cache 服务器直接连接的数量。
  • Codis
    Codis 是一个代理中间件,当客户端向 Codis 发送指令时, Codis 负责将指令转发到后面的Redis 来执行,并将结果返回给客户端。一个 Codis 实例可以连接多个 Redis实例,也可以启动多个 Codis 实例来支撑,每个 Codis 节点都是对等的,这样可以增加整体的QPS需求,还能起到容灾功能。

Redis Cluster特点:

  • 所有的节点相互连接、集群节点不会代理查询
  • 集群消息通信通过集群总线通信,集群总线端口大小为客户端服务端口 + 10000(固定值)
  • 节点与节点之间通过二进制协议进行通信
  • 客户端和集群节点之间通信和通常一样,通过文本协议进行
  • 数据按照 Slot 存储分布在多个 Redis 实例上、可以相对平滑扩/缩容节点
  • 集群节点挂掉会自动故障转移

Redis 没有使用哈希一致性算法,而是使用哈希槽。Redis 中的哈希槽一共有 16384个,计算给定密钥的哈希槽,我们只需要对密钥的 CRC16 取摸 16384。假设集群中有 A、B、C 三个集群节点,且不存在复制模式下,每个集群的节点包含的哈希槽如下:节点 A 包含从 0 到 5500 的哈希槽;节点 B 包含从 5501 到 11000 的哈希槽;节点 C 包含从 11001 到 16383 的哈希槽;这时,如果节点 B 出现故障,整个集群就会出现缺少 5501 到 11000 的哈希槽范围而不可用。


Redis性能优化方向:

  • Master 最好不要做任何持久化工作,如 RDB 内存快照和 AOF 日志文件;
  • 如果数据比较重要,某个 Slave 开启 AOF 备份数据,策略设置为每秒同步一次;
  • 为了主从复制的速度和连接的稳定性,Master 和 Slave 最好在同一个局域网内;
  • 尽量避免在压力很大的主库上增加从库;
  • 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3….;这样的结构方便解决单点故障问题,实现 Slave 对 Master 的替换。如果 Master 挂了,可以立刻启用 Slave1 做 Master,其他不变。

十、Redis事务

redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。Redis事务功能是通过MULTI、EXEC、DISCARD和WATCH 四个原语实现的
1.事务开始-MULTI 开启一个事务,它总是返回OK。 MULTI执行之后,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中
2.命令入队-针对队列的操作:DISCARD 清空事务队列,并放弃执行事务, 并且客户端会从事务状态中退出。WATCH 命令是一个乐观锁,可以为 Redis 事务提供 check-and-set (CAS)行为。 可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令。
3.事务执行-EXEC执行所有事务块内的命令。返回事务块内所有命令的返回值,按命令执行的先后顺序排列。事务执行过程中,如果服务端收到有EXEC、DISCARD、WATCH、MULTI之外的请求,将会把请求放入队列中排队

  • redis 不支持回滚,“Redis 在事务失败时不进行回滚,而是继续执行余下的命令”, 所以 Redis 的内部可以保持简单且快速。如果在一个事务中的命令出现错误,那么所有的命令都不会执行;如果在一个事务中出现运行错误,那么正确的命令会被执行,
  • Redis的事务具备C一致性和I隔离性,依据持久化机制(AOF模式且appendfsync选项的值为always)也具备持久性,不具备原子性(因为不支持回滚)。

十一、缓存雪崩、缓存穿透、缓存击穿

1、缓存击穿:缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决方案:1>设置热点数据永远不过期 2>加互斥锁,互斥锁缓存预热(系统上线后,将相关的缓存数据直接加载到缓存系统)
2、缓存雪崩:缓存同一时间大面积的失效,请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。
解决方案:1>缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生 2>一般并发量不是特别多的时候,使用多的解决方案是加锁排队 3>给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值