Redis

1.介绍一下Redis

Redis 是一款使用 C 语言编写的高性能 key-value 数据库,开源免费,遵守 BSD 协议。

性能极高,能到 100000 次/s 读写速度

支持数据的持久化,对数据的更新采用Copy-on-write技术,可以异步地保存到磁盘上

丰富的数据类型,String(字符串)、List(列表)、Hash(字典)、Set(集合)、Sorted Set(有序集合)

原子性:Redis 的所有操作都是原子性的,多个操作通过 MULTI 和 EXEC 指令支持事务

丰富的特性:key 过期、publish/subscribe、notify

支持数据的备份,快速的主从复制

节点集群,很容易将数据分布到多个Redis实例中

2.Redis支持哪些数据类型?

Redis 支持五种数据类型

string:字符串

hash:哈希

list:列表

set:集合

sorted set:有序集合

3.Redis有哪些优缺点?

优点:

性能极高,能到 100000 次/s 读写速度

支持数据的持久化,对数据的更新采用Copy-on-write技术,可以异步地保存到磁盘上

丰富的数据类型,String(字符串)、List(列表)、Hash(字典)、Set(集合)、Sorted Set(有序集合)

原子性:Redis 的所有操作都是原子性的,多个操作通过 MULTI 和 EXEC 指令支持事务

丰富的特性:key 过期、publish/subscribe、notify

支持数据的备份,快速的主从复制

节点集群,很容易将数据分布到多个Redis实例中

缺点:

数据库容量受到物理内存的限制,不能用作海量数据的高性能读写

适合的场景主要局限在较小数据量的高性能操作和运算上

4.Redis使用单线程模型为什么性能依然很好?

避免了线程切换的资源消耗

单线程不存在资源共享与竞争,不用考虑锁的问题

基于内存的,内存的读写速度非常快

使用非阻塞的 IO 多路复用机制

数据存储进行了压缩优化

使用了高性能数据结构,如 Hash、跳表等

5.Redis持久化机制有哪些?各有什么优缺点?

 RDB 和 AOF

指用数据集快照的方式半持久化模式,记录 redis 数据库的所有键值对,在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,可恢复数据。

优点:

只有一个文件 dump.rdb,恢复操作简单,容灾性好

性能较高,fork 子进程进行写操作,主进程继续处理命令

大数据集比 AOF 的恢复效率高

缺点:

数据安全性低,RDB 是每间隔一段时间进行持久化,若期间 redis 发生故障,可能会发生数据丢失

AOFAppend-only file

指所有的命令行记录以 redis 命令请求协议的格式完全持久化存储,保存为 aof 文件

优点:

数据安全,aof 持久化可以配置 appendfsync 属性为 always,记录每个命令操作到 aof 文件中一次;通过 append 模式写文件,即使中途服务器宕机,也可以通过 redis-check-aof 工具解决数据一致性问题

AOF 机制的 rewrite 模式,AOF 文件没被 rewrite 之前可以进行处理,如删除文件中的 flushall 命令

缺点:

AOF 的持久化文件比 RDB 大,恢复速度慢

6.Redis使用过程中的注意事项?

主库压力很大,可以考虑读写分离

Master 最好不要做持久化工作,如 RDB 内存快照和 AOF 日志文件。(Master 写内存快照,save 命令调度 rdbSave 函数,会阻塞主线程,文件较大时会间断性暂停服务;AOF 文件过大会影响 Master 重启的恢复速度)

如果数据比较重要,使用 AOF 方式备份数据,设置合理的备份频率

保证主从复制的速度和网络连接的稳定性,主从机器最好在同一内网

官方推荐,使用 sentinel 集群配合多个主从节点集群,解决单点故障问题实现高可用

7.Redis过期键的删除策略有哪些?

定时删除:在设置键的过期时间的同时,创建一个定时器,达到过期时间,执行键的删除操作

惰性删除:不主动删除过期键,从键空间中获取键时,都检查取得的键是否过期,过期则删除;没过期则返回

定期删除:每隔一段时间对数据库进行一次检查,删除里面的过期键。删除多少过期键、检查多少个数据库,由算法决定。

8.说说Redis的回收策略

volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中,淘汰最近最少使用的数据

volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中,淘汰最早会过期的数据

volatile-random:从已设置过期时间的数据集(server.db[i].expires)中,随机淘汰数据

allkeys-lru:从数据集(server.db[i].dict)中,淘汰最近最少使用的数据

allkeys-random:从数据集(server.db[i].dict)中,随机淘汰数据

noenviction:Redis 的默认策略,不回收数据,当达到最大内存时,新增数据返回 error

9.zset的内部原理

zset内部是通过skiplist实现的,在链表的基础上加了跳跃的功能。o(logn)。在插入性能上明显优于平衡树。

不需要逐级比较,而是分了很多层,每一个节点的层数是随机的。先从最高层的开始,遇到比目标值大的,就返回。

10.redis为什么这么快

1.完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路I/O复用模型,非阻塞IO;

5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

11.redis的原子性

因为redis是单线程的,很多时候以为所有的操作都是原子性的,也就是一组事务里的操作要么全部执行,要么全部不执行,不存在中间状态。

12.redis的五种数据结构及其使用场景

1. String

常用命令:

get、set、incr、decr、mget等

应用场景:计数,缓存功能:存取一个对象,注:键的取名以“业务名:对象名:id:[属性]”,如mysql:employee:1:name;

2.Hash

应用场景:存储用户信息

3.list,redis的list类型其实就是每个元素都是String类型的双向链表

如好友队列,粉丝队列,消息队列,最新消息排行,微博 TimeLine等

4.set 

redis为集合提供了求交集、并集、差集等操作

集合有取交集、并集、差集等操作,因此可以求共同好友、共同兴趣、分类标签等。

利用唯一性,可以统计访问网站的所有独立 IP。

5.sorted Set--有序集合

和Sets相比,Sorted Sets是将 Set 中的元素增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列。

按时间排序的时间轴

带有权重的元素,比如一个游戏的用户得分排行榜

比较复杂的数据结构,一般用到的场景不算太多

6.缓存穿透

用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
(1)布隆过滤器

使用布隆过滤器进行过滤,把所有可能的查询放在布隆过滤器中。当用户想要查询的时候,使用布隆过滤器发现不在集合中,就直接丢弃,不再对持久层查询。

(2)缓存空对象

当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源。如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。

缓存雪崩

缓存雪崩是指,缓存层出现了错误,不能正常工作了。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。

解决方案:

(1)redis高可用

这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作,

(2)限流

这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

(3)数据预热

数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

缓存击穿

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求持久层数据库。

解决方法,

1.使用互斥锁

该方法是比较普遍的做法,即,在根据key获得的value值为空时,先锁上,再从数据库加载,加载完毕,释放锁。若其他线程发现获取锁失败,则睡眠50ms后重试。

7.redis集群

1.主从复制

一主多从, 主负责写,并且将数据复制到其它的 slave 节点,从节点负责读。 所有的读请求全部走从节点。这样也可以很轻松实现水平扩容,支撑读高并发。这样也可以很轻松实现水平扩容,支撑读高并发。高可用性,读写分离。

主从复制原理:

 Redis主从复制分为全量复制和增量复制。

从服务器连接主服务器,发送psync命令;

主服务器接收到SYNC命名后,开始执行BGSAVE命令生RDB文件并使用缓冲区记录此后执行的所有写命令;

主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令; 

从服务器收到快照文件后丢弃所有旧数据,载入收到的快照; 

主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;

从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;


增量复制一般是 Slave初始化后开始正常工作时,主服务器发生的写操作同步到从服务器的过程。步骤如下:

如果全量复制过程中,master-slave 网络连接断掉,那么 slave 重新连接 master 时,会触发增量复制。

master 直接从自己的 backlog 中获取部分丢失的数据,发送给 slave node,默认 backlog 就是 1MB。

master 就是根据 slave 发送的 psync 中的 offset 来从 backlog 中获取数据的。

当主服务器发生故障后,特别麻烦,需要手动将从节点,升级为主服务器,

哨兵模式

每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个 PING 命令。

如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线(SDOWN)

如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态

当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线(ODOWN)

在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO 命令。

当Master主服务器被 Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的 Master主服务器的所有 Slave从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。

若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线状态就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。

哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。

主从可以自动切换,系统更健壮,可用性更高。

缺点:

Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。

3.Redis-Cluster集群

Redis Cluster 集群节点最小配置 6 个节点以上(3 主 3 从),其中主节点提供读写操作,从节点作为备用节点,不提供请求,只作为故障转移使用。

redis的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台redis服务器都存储相同的数据,很浪费内存,所以在redis3.0上加入了cluster模式,实现的redis的分布式存储,也就是说每台redis节点上存储不同的内容。

 Redis-Cluster采用无中心结构,它的特点如下:

所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。

节点的fail是通过集群中超过半数的节点检测失效时才生效。

客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。

工作方式:

在redis的每一个节点上,都有这么两个东西,一个是插槽(slot),它的的取值范围是:0-16383。还有一个就是cluster,可以理解为是一个集群管理的插件。所有的键根据哈希函数映射到 0~16383 个整数槽内,,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。

优点:

无中心架构;

数据按照 slot 存储分布在多个节点,节点间数据共享,可动态调整数据分布;

可扩展性:可线性扩展到 1000 多个节点,节点可动态添加或删除;

高可用性:部分节点不可用时,集群仍可用。通过增加 Slave 做 standby 数据副本,能够实现故障自动 failover,节点之间通过 gossip 协议交换状态信息,用投票机制完成 Slave 到 Master 的角色提升;

降低运维成本,提高系统的扩展性和可用性。

8.缓存和数据库双写一致性

如果仅仅查询的话,缓存的数据和数据库的数据是没问题的。但是,当我们要更新时候呢?各种情况很可能就造成数据库和缓存的数据不一致了。

解决这个问题的最经典的模式,就是Cache Aside Pattern

Cache Aside Pattern:

   (1)读的时候先读缓存,如果缓存不存在的话就读数据库,取出数据库后更新缓存;如果存在的话直接读取缓存的信息。

    (2)写的时候,先更新数据库,再删除缓存。

1.写的时候为什么是删除缓存,而不是更新缓存?

      删除缓存而不是更新缓存,是一种延迟加载的思想,不是每次都重复更新缓存,只有用到的时候才去更新缓存,同时即使有大量的读请求,实际也就更新了一次,后面的请求不会重复读。

2.Cache aside pattern 存在的问题

先更新数据库,再删除缓存,如果删除缓存失败了,导致数据库中是新数据,缓存中是旧数据,就出现数据不一致的问题。

解决思路:先删除缓存,再更新数据库

1.缓存删除失败:如果缓存删除失败,那么数据库信息没有被修改,保持了数据的一致性;

2.缓存删除成功,数据库更新失败:此时数据库里的是旧数据,缓存是空的,查询时发现缓存不存在,就查询数据库并更新缓存,数据保持一致。

3.上述方案依然存在问题

上面的方案存在不足,在并发情况下会出现问题。如果删除完缓存更新数据库时,如果一个请求过来查询数据,缓存不存在,就查询数据库的旧数据,更新旧数据到缓存中。随后数据更新完成,修改了数据库的数据,此时缓存和数据库的数据就会出现不一致了。高并发下会出现这种数据库+缓存不一致的情况。 如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。

解决方案:采用双删除策略。写请求先删除缓存,再去更新数据库,等待一段时间后异步删除缓存。这样可以保证在读取错误数据时能及时被修正过来。还有一个策略是将删除缓存、修改数据库、读取缓存等的操作积压到队列里边,实现串行化。

9.redis是如何做到高可用的

如果系统99%的时间都用于对外服务,那么系统可以说是高可用的。

哨兵模式可以实现高可用。因为从服务器挂掉了,并不会有太大的影响。主服务器挂掉了,可以将从服务器升级为主服务器。

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