Redis详细介绍

Redis是什么

redis是nosql(也是个巨大的map), 单线程,但是可处理1秒10w的并发(数据都在内存中)。

特点:

  • nosql
  • 单线程
  • 内存存储
  • 高速
  • 并发

注意:单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程。

Redis数据类型

  1. 字符串,SET、GET
  2. 哈希表,HSET、HGET
  3. 列表,LPUSH、LPOP、RPUSH、RPOP
  4. 集合(set),SADD、SPOP操作
  5. 有序集合(有序set),ZADD、ZSCORE、ZRANGE

Redis是单线程为何还那么快

原因主要有:

  1. 纯内存操作
  2. 单线程操作,避免了频繁的上下文切换
  3. 采用了非阻塞I/O多路复用机制

纯内存操作
数据存放在内存中,内存的响应时间大约是 100纳秒 ,这是Redis每秒万亿级别访问的重要基础。

单线程操作
虽然是采用单线程,但是单线程避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU。

I/O多路复用机制
多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有准备好的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。加上Redis自身的事件处理模型将epoll中的连接,读写,关闭都转换为了事件,不在I/O上浪费过多的时间。

详细IO多路复用机制见:原文

Redis单线程的缺点(如何利用多核CPU)

无法发挥多核CPU性能,不过可以通过在单机开多个Redis实例来完善。

Redis 单线程如何处理并发连接

答案是I/O多路复用机制。
Redis基于Reactor模式开发了自己的网络事件处理器——文件事件处理器。
redis将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。读取数据通过epoll,如果准备好,epoll会通知,随后将数据写入Socket流中返回给客户端。
在这里插入图片描述
转自:https://www.jianshu.com/p/4e6b7809e10a

Redis的持久化(解决突然断电的情况)

Redis可以将数据持久化,将内存中的数据异步写入硬盘中,有两种方式:RDB(默认)和AOF

RDB(默认)

在指定的时间间隔内保存数据快照。

RDB机制
在默认情况下, Redis 将内存数据库快照保存在名字为dump.rdb的二进制文件中。
可以对 Redis 进行设置, 让它在N秒内数据集至少有M个改动这一条件被满足时, 自动保存一次数据集。
例如,每60秒内有1000次改动,自动保存

save 60 1000

RDB触发条件

  • 手动触发:SAVE,阻塞Redis的服务器进程,直到RDB文件被创建完毕
  • 手动触发:BGSAVE,Fork出一个子进程来创建RDB文件,不阻塞服务器进程。
  • 自动触发:save 60 1000
  • 自动触发:主从复制时,主节点自动触发
  • 自动触发:执行Debug Relaod
  • 自动触发:执行shutdown,且没开AOF

RDB优点

  1. 全量数据
  2. 是一个紧凑压缩的二进制文件,Redis加载RDB恢复数据远远快于AOF的方式。

RDB缺点

  1. 可能会导致部分数据丢失,因为是每隔一段时间进行一次持久化
  2. 数据量大时会由于I/O严重影响性能
AOF

先把命令追加到操作日志的尾部,保存所有的历史操作

AOF机制
记录除了查询以外的所有变更数据库状态的指令,以append的形式追加保存到AOF文件中(增量)

AOF优点

  1. 数据非常完整,故障恢复丢失数据少
  2. 可对历史操作进行处理

AOF缺点

  1. 因为AOF模式要把每一步redis命令都记录下来,所以就导致文件的体积会很大
  2. 速度低于RDB,需要定期执行重写操作来降低文件体积
  3. 由原因1,导致恢复速度慢
RDB+AOF混合模式

这样兼容性差,只能用在4.0版本之后,以前没法用

选择哪种模式

建议RDB。
如果非常关心数据, 但仍然可以承受数分钟以内的数据丢失, 那么可以只使用 RDB 持久化。如果无法承受,才选择AOF。

Redis的发布订阅

Redis提供了发布订阅功能,可以用于消息的传输,Redis的发布订阅机制包括三个部分,发布者,订阅者和频道(Channel)。
在这里插入图片描述
发布者和订阅者都是Redis客户端,Channel则为Redis服务器端,发布者将消息发送到某个的频道,订阅了这个频道的订阅者就能接收到这条消息。

工作过程
服务端创建(SUBSCRIBE 命令)一个频道 ,名为channelTest。三个客户端通过订阅(SUBSCRIBE 命令),成为channelTest频道的订阅者。服务端,也就是channelTest频道的发布者,在channelTest频道中发布(PUBLISH 命令)一个消息,三个订阅者均可收到这条消息。

维护机制
每个 Redis 服务器进程都维持着一个pubsub_channels字典。其中,字典的键为正在被订阅的频道, 而字典的值则是一个链表, 链表中保存了所有订阅这个频道的客户端。
在这里插入图片描述
另外,客户端自己也维护了一个pubsub_channels属性,用来记录自己订阅了哪些频道。

转自:https://www.cnblogs.com/lonelyxmas/p/10396046.html

Redis的事物

Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
但是它并不完全与传统数据库事物相同。

特点:

  1. 不保证原子性,可能会成功一半失败一半,并不会回滚。
  2. 没有隔离级别,因为事务提交前任何指令都不会被实际执行,等在事物队列里,所有的事物是通过单线程执行且不会被打断。
  3. 不会被客户端其他命令打断。

为什么不具有隔离性

因为redis使用单线程的方式来执行事务(以及事务队列中的命令),并且服务器保证,在执行事务期间不会对事物进行中断,因此,redis的事务总是以串行的方式运行的,并且事务也总是具有隔离性的 。

执行过程

MULTI命令声明事物开始,EXEC声明事物提交,开始执行事物。
可以通过DISCARD命令结束事物,并丢弃全部的命令序列。
WATCH命令是开始执行乐观锁,UNWATCH命令将取消当前客户端对象的乐观锁key,该客户端对象的事务提交将变成无条件执行.

watch命令
watch命令是一个乐观锁(CAS),它可以在EXEC命令执行之前,监视任意数量的数据库键,并在执行EXEC命令时判断是否至少有一个被watch的键值被修改如果被修改就放弃事务的执行,如果没有被修改就清空watch的信息,执行事务列表里的命令。

为什么需要watch命令
当我们进行多线程同步操作一个key时,比如两个线程对a进行++的操作。
同时读了a = 1之后,同时设置a = 2,对于Redis来说,就是收到两条命令,都是设置a = 2。这就有问题了。
使用watch就可以解决这个问题,执行事务时,如果发现a 已经不等于 1,就不会进行操作。

Redis管道

管道是用来解决什么问题?
Redis是一个响应式的服务,当客户端发送一个请求后,就处于阻塞状态等待Redis返回结果。这样一次命令消耗的时间就包括四个部分:请求从客户端到服务器的时间、命令排队的时间和命令真正执行时间、结果从服务器到客户端的时间,第一个和第四个消耗的时间总和称为RTT(Round Trip Time),当客户端与服务器存在网络延时时,RTT就可能会很大,这样就会导致性能问题。

管道运行机制
利用管道,客户端可以一次性发送多个请求而不用等待服务器的响应,待所有命令都发送完后再一次性读取服务的响应,这样可以极大的降低RTT时间从而提升性能。

并不是打包的命令越多越好
需要注意到是用pipeline方式打包命令发送,redis必须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并不是打包的命令越多越好。

pipeline和“事务”的区别
pipeline和“事务”是两个完全不同的概念,无论如何,pipeline中发送的每个command都会被server立即执行,如果执行失败,将会在此后的响应中得到信息;也就是pipeline并不是表达“所有command都一起成功”的语义。
pipeline只是表达“交互”中操作的传递的方向性,pipeline也可以在事务中运行,也可以不在,但是如果pipeline的操作被封装在事务中,那么将有事务来确保操作的成功与失败。

原文链接:https://blog.csdn.net/qq_24313635/article/details/83054300

Redis过期时间删除策略

立即删除
在设置键的过期时间时,创建一个回调事件,当过期时间达到时,由时间处理器自动执行键的删除操作。

立即删除能保证内存中数据的最大新鲜度,因为它保证过期键值会在过期后马上被删除,其所占用的内存也会随之释放。但是立即删除对cpu是最不友好的。因为删除操作会占用cpu的时间,如果刚好碰上了cpu很忙的时候,比如正在做交集或排序等计算的时候,就会给cpu造成额外的压力。

而且目前redis事件处理器对时间事件的处理方式–无序链表,查找一个key的时间复杂度为O(n),所以并不适合用来处理大量的时间事件。

惰性删除
键过期了就过期了,不管。每次从dict字典中按key取值时,先检查此key是否已经过期,如果过期了就删除它,并返回nil,如果没过期,就返回键值。

惰性删除是等到下次被使用的时候,才会被检查到过期,此时才能得到删除。所以惰性删除的缺点很明显:浪费内存。dict字典和expires字典都要保存这个键值的信息。

定时删除
每隔一段时间,对expires字典进行检查,删除里面的过期键。

立即删除会短时间内占用大量cpu,惰性删除会在一段时间内浪费内存,所以定时删除是一个折中的办法。定时删除是通过限制删除操作执行的时长和频率,来减少删除操作对cpu的影响。另一方面定时删除也有效的减少了因惰性删除带来的内存浪费。

redis使用的策略
redis使用的过期键值删除策略是:惰性删除加上定期删除,两者配合使用。

原文链接:https://blog.csdn.net/jiangchunhui2009/article/details/81504073

转自:https://blog.csdn.net/zlc3323/article/details/80836881

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值