这是一份Redis学习总结,请查收

最近又复习了一下redis中比较重要的几个知识点,知识点多且碎,在这里做一个简单的总结,便于以后复习。

主流应用架构

我们都知道多数情况下redis是作为缓存应用来使用的,下面则显示出当前主流的应用架构(客户端、缓存、存储层).


主流应用架构.png

对比缓存中间件 Memcache和Redis的区别

⭐️Memcache: 在代码层次上比较类似于Hash
  • 支持简单的数据类型
  • 不支持数据持久化存储
  • 不支持主从
  • 不支持分片
⭐️Redis
  • 数据类型丰富
  • 支持数据磁盘持久化存储(RDB、AOF)
  • 支持主从
  • 支持分片

我们知道,Redis是内存级数据库,它的QPS(Query Per Second)可以达到100000+,那它为啥那么快呢?

原因如下:

  1. 完全基于内存,绝大多数是存粹的内存操作
  2. 数据结构简单,对数据操作简单(如利用了Hash的查找为O(1)的特性)
  3. 采用单线程(在处理网络请求时是单线程),单线程也能处理高并发的需求,如果想要多核的话可以启动多个实例
  4. 使用多路I/O复用模型,非阻塞I/O

下面我们便开始聊一聊Redis的多路I/O复用模型,在聊这个之前,我们首先应该清楚一个概念:

FD 文件描述符(File Descripto):一个打开的文件通过唯一的描述符进行引用,该描述符是打开文件元数据到文件本身的映射.

I/O模型有:1.传统的I/O阻塞模型 2.多路I/O复用模型(可以同时对多个fd的状态进行监控)

IO多路复用.png

Redis采用的I/O多路复用函数: epoll/kqueue/evport/select

优先选择O(1)的I/O多路复用函数作为底层实现,以时间复杂度为O(n)的来保底,基于react设计监听I/O事件(监听多个fd)

简单聊一下Redis的数据类型

1.String k,v 最基本的类型,二进制安全(可存图片) [incr 可用作网站用户量统计]
2.Hash String元素组成的字典,适合存储对象。hmset lilei name "lilei" age 26 title "senior"
3.List列表 按照插入顺序排序 lpush rpush. 查询0-10的记录 orange mylist 0 10
4.Set String元素的无序集合,不重复。可以进行交、差、并等操作。sadd myset 111。smembers myset —>遍历所有元素
5.Sorted Set 通过分数为元素大小排序,不重复 zadd myzset 3 abc ; zrangebyscore myset 0 10
还有一些比较高级的如用于计数的HyperLogLog和用于支持存储地理位置的Geo

此外可以看一下<<Redis的设计与实现>>这本书中对于Redis底层数据类型基础的介绍,以上的所有对象都是基于更加底层的数据结构实现的

如何从海量数据里(2000w+)查询出某一个固定前缀的key

遇到这种问题时,应该首先问清楚数据量的范围规模,问清楚边界,再进行思考和回答

KEYS pattern : 查找所有符合给定模式pattern 的key, 例如 keys k1 查找所有以k1开头的key*

使用keys 对线上业务有什么影响?

keys指令会一次性返回所有匹配的key,键的数量太大会导致服务卡顿

为了解决这个问题 引入了SCAN cursor
  • 基于游标cursor的迭代器,需要基于上一次游标延续之前的迭代过程,以0作为游标作为一次新的迭代,直到返回游标0完成一次遍历。

  • 不保证每次执行都返回某个给定数量的元素,支持模糊查询。

  • 一次返回的数量不可控,只能是大概率符合count参数

    Scan 0 match k1* count 10

    可能获取的数据数量不是10条,可能获得重复元素,要在程序中去重

如何通过Redis实现分布式锁?

要想实现分布式锁,我们需要考虑到以下需求:

  • 互斥性
  • 安全性
  • 注意死锁问题
  • 容错

可以利用Redis如下命令的特性实现一个分布式锁

SETNX key value :如果key不存在,创建并且赋值(用key作为锁)

但这样是占有了一个锁,如何释放掉它呢?也就是说如何解决SETNX长期有效的问题

EXPIRE key seconds :设置过期时间删除模拟锁的释放

下面看一个伪代码的实现

long status = redisService.setnx(key,"1");
//注释1
if(status==1){
    redisService.expire(key,expire);
    doSomething();//......
}

上面的代码看上去似乎没有什么问题,但是仔细想想,如果执行到注释1的地方的时候,redis服务器发生了宕机怎么办? 所以我们要保证setnx操作和expire的设置是原子的

所以redis引入了以下命令

set locktarget 12345(可以写线程的标识) ex 10 nx  //该操作是个原子操作,成功返回OK,失败返回nil

伪代码实现:

String result = redisService.set(lockkey,requestId,SET_IF_NOT_EXIST,SET_WITH_EXPIRE_TIME,expiretime);

if("OK".equals(result)){
    doSomething();//....
}

大量的key同时过期怎么处理?

key集中过期,清除大量的key很耗时,会出现短暂的卡顿现象

解决方案: 在设置key的过期时间的时候,给每个key加上随机的值

如何用Redis做异步队列?

使用list做异步队列, rpush生产消息,lpop消费消息

缺点:没有等待队列里有值就进行直接消费

弥补:可以在应用层引入sleep机制去调用lpop重试

也可以用以下命令

BLPOP key[key...] timeout : 阻塞直到队列有消息或者超时

缺点:只能供一个消费者消费

Pub/Sub 主题订阅模式

主题订阅模式.png

这里有三个客户端连接 分别为cli-1、cli-2、cli-3

cli1:6379-> subscribe myTopic
cli2:6379-> subscribe myTopic
cli3:6379-> publish myTopic "Hello"

然后cli1 和 cli3便会接收到hello消息

这里请注意: 消息的发布是无状态的,无法保证可达

Redis如何做持久化?

1.RDB(快照)持久化:保存某个时间点的全量数据快照
在redis.conf 中可以配置 RDB持久化方式的持久化策略
  • save 900 1 //在900s内进行一次写操作触发持久化
  • save 300 10
  • Save 60 10000
stop-writes-on-bgsave-error yes

当备份进程出错误时,主进程停止接受新的写入操作(保证持久化的数据一致性问题)

rdbcompression no

建议设置为no,关闭压缩,降低cpu损耗(因为Redis本身就是CPU密集型)

手动持久化的命令

1.SAVE : 阻塞Redis的服务器进程直到RDB文件被创建完毕

2.BGSAVE: fork出一个子进程来创建RDB文件,不阻塞服务器进程

自动触发RDB持久化的方式
  • 根据redis.conf配置的save m n 定时触发(用的bgsave)
  • 主从复制时,主节点自动触发
  • 执行debug reload
  • 执行shutdown 且没有开启ROF持久化

什么是 Copy-On-Write 写时复制?

如果有多个调用者同时获取相同的资源的时候,他们会获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容的时候,系统才会真正复制一份专有副本给调用者,而其他调用者见到的最初资源保持不变。

当redis做持久化时,redis会fork一个子进程,将数据写入磁盘中的一个临时的rdb文件中,当子进程完成写临时文件之后,将原来的rdb替换掉,这样的好处是可以实现copy-on-write,子进程继续可以接受其他请求,确保了redis性能。

缺点:内存数据的全量同步,当数据量大的时候会由于I/O而严重影响性能,可能会因为redis挂掉而丢失从当前至最近一次快照期间的数据。

2.AOF(Append-Only-File)持久化:保存写状态
  • 记录下除了查询以外所有变更数据库状态的指令
  • 以append的形式追加保存到AOF文件中(增量)

AOF的持久化默认是关闭的. vim redis.conf

appendonlyno. —>修改为 appendonly yes 生效

appendfilename "append only.aof"

appendfsync:可以指定AOF写入方式 :

1.always 2.everysec 3.no

AOF日志重写 bgrewrite aof

日志重写解决AOF文件大小不断增大的问题,原理如下:

  1. 调用fork(),创建一个子进程
  2. 子进程把新的AOF写到一个临时文件里,不依赖原来的AOF文件
  3. 主进程持续把新的变动同时写入内存和原来的AOF里
  4. 主进程获取子进程的重写AOF的完成信号,往新的AOF同步增量变动
  5. 使用新的AOF文件替换掉旧的AOF文件

Redis数据的恢复

RDB和AOF文件共存情况下的恢复流程
Redis数据的恢复流程.png

RDB-AOF混合持久化的方式

BGSAVE做镜像全量持久化,AOF做增量持久化

总结RDB和AOF的优缺点

  • RDB优点:全量数据快照,文件小,恢复快
  • RDB缺点:无法保存最近一次快照后的数据
  • AOF优点:可读性高,适合保存增量数据,数据不易丢失
  • AOF缺点:文件体积大,恢复时间长

Redis主从复制同步

1.全同步过程
  1. Slave发送sync命令到master
  2. master启动一个后台进程,将redis中的数据快照保存到文件中
  3. master将保存快照期间收到的命令缓存起来
  4. master完成写文件操作后,将该文件发送给salve
  5. 使用新的AOF文件替换掉旧的AOF文件
  6. master将这期间收到的写命令发送给salve,进行回放
2.增量同步的过程
  1. master接受用户的操作指令,判断是否需要传播到salve
  2. 将操作记录追加到aof文件
  3. 将操作传播到其他slave:1.对齐主从库 2.往响应缓存中写入指令
  4. 将缓存中的数据发送给slave

主从模式不具备高可用性,当master挂掉以后,slave将无法对外提供写入操作,为解决该问题,引入redis sentinel(哨兵)解决主从同步宕机后的主从切换问题

  • 监控:检查主从服务器是否运行正常
  • 提醒:通过API向管理员或者其他应用程序发送故障通知
  • 自动故障转移:主从切换

流言协议 Gossip 在杂乱无章中寻求一致

每个节点都随机与对方通信,最终所有节点的状态达成一致。

种子节点定期随机向其他节点发送节点列表以及需要传播的信息

不保证信息一定会传递给所有的节点,但最终会趋于一致性。

关于redis集群的更多总结我会放到下一篇文章里,今天的总结就到这里了!

lhsjohn 转载请注明出处 谢谢!
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 一、Redis高可用概述 在介绍Redis高可用之前,先说明一下在Redis的语境中高可用的含义。 我们知道,在w...
    空语阅读 1,593评论 0 2
  • 原帖地址:https://www.jianshu.com/p/2f14bc570563 redis概述 Redis...
    onlyHalfSoul阅读 2,154评论 0 28
  • 企业级redis集群架构的特点 海量数据 高并发 高可用 要达到高可用,持久化是不可减少的,持久化主要是做灾难恢复...
    lucode阅读 2,192评论 0 7
  • Redis是啥 Redis是一个开源的key-value存储系统,由于拥有丰富的数据结构,又被其作者戏称为数据结构...
    一凡呀阅读 1,170评论 0 5
  • 【作者】夏晓 【导师】王玉印 【总舵主】焦杨 易琳 【分舵主】向燚 参考别人的导图原理和要素。发散,收敛,关键词重...
    文魁大脑夏晓阅读 391评论 0 0