目录
23、Redis 与其他 key-value 存储有什么不同?
25、Redis 是单线程的, 如何提高多核 CPU 的利用率?
1、NOSql,Redis 优点
NoSQL(not only SQL),非关系型数据库,数据存储不需要固定的格式
redis 优缺点:
优点
-
读写性能优异, Redis能读的速度是110000次/s,写的速度是81000次/s。
-
支持数据持久化,支持AOF和RDB两种持久化方式。
-
支持事务,Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并 后的原子性执行。
-
数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等 数据结构。
-
支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
缺点
-
数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis 适合的场景主要局限在较小数据量的高性能操作和运算上。
-
Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求 失败,需要等待机器重启或者手动切换前端的IP才能恢复。
-
主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一 致的问题,降低了系统的可用性。
-
Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避 免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的 浪费。
常见的NOSQL数据库:
memcached:键值对,内存型数据库,所有数据都在内存中,断电数据会丢失
Redis:和mamcached类似,还具备持久化能力。
HBase:以列作为存储
MongoDB:以document作为存储
2、Redis 数据类型
- 1)String:字符串【key-value】
- 2) Hash:散列【key-field-value】
- 3)List :列表
- 4)Set:集合
- 5)Sorted Set:有序集合【key-score-member】
据类型 | 可以存储 的值 | 操作 | 应用场景 |
---|---|---|---|
STRING | 字符串、 整数或者 浮点数 | 对整个字 符串或者 字符串的 其中一部 分执行操 作 对整数和 浮点数执 行自增或 者自减操 作 | 做简单的 键值对缓 存 |
LIST | 列表 | 从两端压 入或者弹 出元素 对单个或 者多个元 素进行修 剪, 只保留一 个范围内 的元素 | 存储一些 列表型的 数据结 构,类似 粉丝列 表、文章 的评论列 表之类的 数据 |
SET | 无序集合 | 添加、获 取、移除 单个元素 检查一个 元素是否 存在于集 合中 | 交集、并 集、差集 的操作, 比如交 集,可以 把两个人 的粉丝列 |
HASH | 包含键值 对的无序 散列表 | 添加、获 取、移除 单个键值 对 获取所有 键值对 检查某个 键是否存 在 | 结构化的 数据,比 如一个对 象 |
ZSET | 有序集合 | 添加、获 取、删除 元素 根据分值 范围或者 成员来获 取元素 计算一个 键的排名 | 去重但可 以排序, 如获取排 名前几名 的用户 |
3、Redis常用命令
通用命令
- exists key :判断key是否存在
- del key :删除key
- expire key seconds:设置key过期时间
- ttl key:查询key剩余过期时间
---String----
- set key value
- get key
---Hash----
- hset key field value 设置key中某字段值
4、Redis协议
Redis 协议与客户端通过RESP(Redis Serialization Protocol)协议通信,是基于TCP的应用层协议,默认端口6379
RESP协议特点:容易实现,解析快,人类可读
5、Redis架构模式
- 1)单机版:简单,内存容量有限,处理能力有限,无法高可用
- 2)主从复制:允许一主多从,被复制的是主服务器master,复制品是从服务器slave,slave只读,能缓解主服务器的压力,无法分解写压力,无法高可用
- 3)哨兵:Sentinel会不断的检查主服务器和从服务器是否正常运行,当一个主服务器不能正常工作时,哨兵会开始一次自动故障迁移,它会将失效主服务器中的其中一个从服务器升级为新的主服务器使得集群可以使用新的主服务器代替失效服务器
- 4)集群:使用hash槽,集群的每个节点负责一部分hash值,分散写压力,使用主从复制模式,主节点失效,会自动选举从节点为新主,不能保证数据一致性。
6、Redis持久化
RDB,AOF
RDB:
RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保 存到硬盘中,对应产生的数据文件为dump.rdb。通过配置文件中的save参数来 定义快照的周期。
优点:
-
只有一个文件 dump.rdb,方便持久化。
-
容灾性好,一个文件可以保存到安全的磁盘。
-
性能大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO 大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能
-
相对于数据集大时,比 AOF 的启动效率更高。
缺点:
-
数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发 生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)
-
AOF(Append-only file)持久化方式: 是指所有的命令行记录以 redis 命 令请 求协议的格式完全持久化存储)保存为 aof 文件。
AOF:持久化
AOF持久化(即Append Only File持久化),则是将Redis执行的每次写命令记录 到单独的日志文件中,当重启Redis会重新将持久化的日志中文件恢复数据。 当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。
优点:
-
数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一 次 命令操作就记录到 aof 文件中一次。
-
通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-checkaof 工具解决数据一致性问题。
-
AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命 令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))
缺点:
-
AOF 文件比 RDB 文件大,且恢复速度慢。
-
数据集大的时候,比 rdb 启动效率低。
优缺点是什么?
-
AOF文件比RDB更新频率高,优先使用AOF还原数据。
-
AOF比RDB更安全也更大
-
RDB性能比AOF好
-
如果两个都配了优先加载AOF
# 7、为什么要用 Redis /为什么要用缓存
主要从“高性能”和“高并发”这两点来看待这个问题。
高性能:
假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上 读取的。将该用户访问的数据存在数缓存中,这样下一次再访问这些数据的时候 就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。如 果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可!
高并发:
直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑 把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这 里而不用经过数据库。
10、redis 设置密码
- redis密码验证:127.0.0.1:6379> auth 1234
- 设置密码:127.0.0.1:6379> config set requirepass 1234
11、redis 过期时间设置
- 设置过期时间:127.0.0.1:6379> expire expire 3600
- 得到过期时间:127.0.0.1:6379> ttl expire
12、相比 memcached 有哪些优势
- (1) memcached 所有的值均是简单的字符串, Redis 作为其替代者, 支持更为丰富的数据类型
- (2)Redis 的速度比 memcached 快很多
- (3) Redis 可以持久化其数据
13、Redis 有哪几种数据淘汰策略?
- (1)noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令, 但 DEL 和几个例外)
- (2)allkeys-lru: 尝试回收最少使用的键(LRU), 使得新添加的数据有空间存放。
- (3)volatile-lru: 尝试回收最少使用的键(LRU), 但仅限于在过期集合的键,使得新添加的数据有空间存放。
- (4)allkeys-random: 回收随机的键使得新添加的数据有空间存放。
- (5)volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
- (6)volatile-ttl: 回收在过期集合的键, 并且优先回收存活时间(TTL) 较短的键,使得新添加的数据有空间存放
14、redis为什么采用跳表而不是红黑树
在做范围查找的时候,平衡树比skiplist操作要复杂。在平衡树上,我们找到指定范围的小值之后,还需要以中序遍历的顺序继续寻找其它不超过大值的节点。如果不对平衡树进行一定的改造,这里的中序遍历并不容易实现。而在skiplist上进行范围查找就非常简单,只需要在找到小值之后,对第1层链表进行若干步的遍历就可以实现。
平衡树的插入和删除操作可能引发子树的调整,逻辑复杂,而skiplist的插入和删除只需要修改相邻节点的指针,操作简单又快速。
从内存占用上来说,skiplist比平衡树更灵活一些。一般来说,平衡树每个节点包含2个指针(分别指向左右子树),而skiplist每个节点包含的指针数目平均为1/(1-p),具体取决于参数p的大小。如果像Redis里的实现一样,取p=1/4,那么平均每个节点包含1.33个指针,比平衡树更有优势。
查找单个key,skiplist和平衡树的时间复杂度都为O(log n),大体相当;而哈希表在保持较低的哈希值冲突概率的前提下,查找时间复杂度接近O(1),性能更高一些。所以我们平常使用的各种Map或dictionary结构,大都是基于哈希表实现的。
从算法实现难度上来比较,skiplist比平衡树要简单得多。
15、为什么 Redis 需要把所有数据放到内存中?
Redis 为了达到最快的读写速度将数据都读到内存中, 并通过异步的方式将数据写入磁盘。
所以 Redis 具有快速和数据持久化的特征。 如果不将数据放在内存中, 磁盘 I/O 速度为严重
影响 Redis 的性能。 在内存越来越便宜的今天, Redis 将会越来越受欢迎。
16、LRU?redis里的具体实现?
LRU全称是Least Recently Used,即最近最久未使用的意思。
LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。
redis原始的淘汰算法简单实现:当需要淘汰一个key时,随机选择3个key,淘汰其中间隔时间最长的key。**基本上,我们随机选择key,淘汰key效果很好。后来随机3个key改成一个配置项"N随机key"。但把默认值提高改成5个后效果大大提高。考虑到它的效果,你根本不用修改他。
17、redis的持久化?
- RDB持久化可以手动执行,也可以配置定期执行,可以把某个时间的数据状态保存到RDB文件中,反之,我们可以用RDB文件还原数据库状态。
- AOF持久化是通过保存服务器执行的命令来记录状态的。还原的时候再执行一遍即可。
18、Redis 有哪些适合的场景?
- (1)、 会话缓存(Session Cache)
最常用的一种使用 Redis 的情景是会话缓存(session cache)。 用 Redis 缓存会话比其他
存储(如 Memcached) 的优势在于: Redis 提供持久化。 当维护一个不是严格要求一致性
的缓存时, 如果用户的购物车信息全部丢失, 大部分人都会不高兴的, 现在, 他们还会这样
吗?
幸运的是, 随着 Redis 这些年的改进, 很容易找到怎么恰当的使用 Redis 来缓存会话的文
档。 甚至广为人知的商业平台 Magento 也提供 Redis 的插件。
-
(2)、 全页缓存(FPC)
除基本的会话 token 之外, Redis 还提供很简便的 FPC 平台。 回到一致性问题, 即使重启
了 Redis 实例, 因为有磁盘的持久化, 用户也不会看到页面加载速度的下降, 这是一个极
大改进, 类似 PHP 本地 FPC。
再次以 Magento 为例, Magento 提供一个插件来使用 Redis 作为全页缓存后端。
此外, 对 WordPress 的用户来说, Pantheon 有一个非常好的插件 wp-Redis, 这个插件
能帮助你以最快速度加载你曾浏览过的页面。
-
(3)、 队列
Reids 在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得 Redis 能作为一个
很好的消息队列平台来使用。 Redis 作为队列使用的操作, 就类似于本地程序语言(如
Python) 对 list 的 push/pop 操作。
如果你快速的在 Google 中搜索“Redis queues”, 你马上就能找到大量的开源项目, 这些
项目的目的就是利用 Redis 创建非常好的后端工具, 以满足各种队列需求。 例如, Celery
有一个后台就是使用 Redis 作为 broker, 你可以从这里去查看。
- (4)、 排行榜/计数器
Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted
Set) 也使得我们在执行这些操作的时候变的非常简单, Redis 只是正好提供了这两种数据
结构。 所以, 我们要从排序集合中获取到排名最靠前的 10 个用户–我们称之为
“user_scores”, 我们只需要像下面一样执行即可:
当然, 这是假定你是根据你用户的分数做递增的排序。 如果你想返回用户及用户的分数, 你
需要这样执行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games 就是一个很好的例子, 用 Ruby 实现的, 它的排行榜就是使用 Redis 来存储
数据的, 你可以在这里看到。
- (5)、 发布/订阅
最后 是 Redis 的发布/订阅功能。 发布/订阅的使用场景确实非
常多。 我已看见人们在社交网络连接中使用, 还可作为基于发布/订阅的脚本触发器, 甚至
用 Redis 的发布/订阅功能来建立聊天系统。
说说 Redis 哈希槽的概念?
Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念, Redis 集群有 16384 个哈希槽,
每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽, 集群的每个节点负责一部分
hash 槽
19、Redis 集群会有写操作丢失吗? 为什么?
Redis 并不能保证数据的强一致性, 这意味这在实际中集群在特定的条件下可能会丢失写操
作。
20、Redis 集群方案应该怎么做?都有哪些方案?
- 1.twemproxy,大概概念是,它类似于一个代理方式, 使用时在本需要连接 redis 的地方改为连接 twemproxy, 它会以一个代理的身份接收请求并使用一致性 hash 算法,将请求转接到具体 redis,将结果再返回 twemproxy。缺点: twemproxy 自身单端口实例的压力,使用一致性 hash 后,对 redis 节点数量改变时候的计算值的改变,数据无法自动移动到新的节点。
- 2.codis,目前用的最多的集群方案,基本和 twemproxy 一致的效果,但它支持在 节点数量改变情况下,旧节点数据可恢复到新 hash 节点
- 3.redis cluster3.0 自带的集群,特点在于他的分布式算法不是一致性 hash,而是 hash 槽的概念,以及自身支持节点设置从节点。具体看官方文档介绍。
21、为什么要做 Redis 分区?
分区可以让 Redis 管理更大的内存, Redis 将可以使用所有机器的内存。 如果没有分区, 你
最多只能使用一台机器的内存。 分区使 Redis 的计算能力通过简单地增加计算机得到成倍提
升,Redis 的网络带宽也会随着计算机和网卡的增加而成倍增长。
22、Redis 分区有什么缺点?
涉及多个 key 的操作通常不会被支持。 例如你不能对两个集合求交集, 因为他们可能被存
储到不同的 Redis 实例(实际上这种情况也有办法, 但是不能直接使用交集指令)。
同时操作多个 key,则不能使用 Redis 事务.
分区使用的粒度是key,不能使用一个非常长的排序key存储一个数据集(The partitioning
granularity is the key, so it is not possible to shard a dataset with a single huge
key like a very big sorted set) .
当使用分区的时候, 数据处理会非常复杂, 例如为了备份你必须从不同的 Redis 实例和主
机同时收集 RDB / AOF 文件。
分区时动态扩容或缩容可能非常复杂。 Redis 集群在运行时增加或者删除 Redis 节点, 能
做到最大程度对用户透明地数据再平衡,但其他一些客户端分区或者代理分区方法则不支持
这种特性。 然而, 有一种预分片的技术也可以较好的解决这个问题。
23、Redis 与其他 key-value 存储有什么不同?
Redis 有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库
的进化路径。 Redis 的数据类型都是基于基本数据结构的同时对程序员透明, 无需进行额外
的抽象。
Redis 运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡
内存, 应为数据量不能大于硬件内存。 在内存数据库方面的另一个优点是, 相比在磁盘上
相同的复杂的数据结构, 在内存中操作起来非常简单, 这样 Redis 可以做很多内部复杂性
很强的事情。 同时, 在磁盘格式方面他们是紧凑的以追加的方式产生的, 因为他们并不需
要进行随机访问
24、Redis 的内存用完了会发生什么?
如果达到设置的上限, Redis 的写命令会返回错误信息(但是读命令还可以正常返回。) 或
者你可以将 Redis 当缓存来使用配置淘汰机制,当 Redis 达到内存上限时会冲刷掉旧的内容。
25、Redis 是单线程的, 如何提高多核 CPU 的利用率?
可以在同一个服务器部署多个 Redis 的实例, 并把他们当作不同的服务器来使用, 在某些时
候, 无论如何一个服务器是不够的,
所以, 如果你想使用多个 CPU, 你可以考虑一下分片(shard)。
一个 Redis 实例最多能存放多少的 keys? List、 Set、Sorted Set 他们最多能存放多少元素?
理论上 Redis 可以处理多达 232 的 keys, 并且在实际中进行了测试, 每个实例至少存放了 2亿 5 千万的 keys。 我们正在测试一些较大的值。
任何 list、 set、 和 sorted set 都可以放 232 个元素。
换句话说, Redis 的存储极限是系统中的可用内存值
26、修改配置不重启 Redis 会实时生效吗?
针对运行实例, 有许多配置选项可以通过 CONFIG SET 命令进行修改, 而无需执行任何
形式的重启。 从 Redis 2.2 开始, 可以从 AOF 切换到 RDB 的快照持久性或其他方式
而不需要重启 Redis。 检索 ‘CONFIG GET *’ 命令获取更多信息。
但偶尔重新启动是必须的, 如为升级 Redis 程序到新的版本, 或者当你需要修改某些目前
CONFIG 命令还不支持的配置参数的时候
27、哨兵
Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。其中三个特性:
监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
提醒(Notification): 被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。
特点:
- 1、保证高可用
- 2、监控各个节点
- 3、自动故障迁移
缺点:主从模式,切换需要时间丢数据
没有解决 master 写的压力
28、缓存穿透
一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就去后端系统查找(比如DB)。
一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
如何避免?
- 1:对查询结果为空的情况也进行缓存,这样,再次访问时,缓存层会直接返回空值。缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。
- 2:对一定不存在的key进行过滤。具体请看布隆过滤器
29、缓存击穿
是针对缓存中没有但数据库有的数据。
场景是,当Key失效后,假如瞬间突然涌入大量的请求,来请求同一个Key,这些请求不会命中Redis,都会请求到DB,导致数据库压力过大,甚至扛不住,挂掉。
解决办法
- 1、设置热点Key,自动检测热点Key,将热点Key的过期时间加大或者设置为永不过期,或者设置为逻辑上永不过期
- 2、加互斥锁。当发现没有命中Redis,去查数据库的时候,在执行更新缓存的操作上加锁,当一个线程访问时,其它线程等待,这个线程访问过后,缓存中的数据会被重建,这样其他线程就可以从缓存中取值。
30、缓存雪崩
是指大量Key同时失效,对这些Key的请求又会打到DB上,同样会导致数据库压力过大甚至挂掉。
解决办法
- 1)让Key的失效时间分散开,可以在统一的失效时间上再加一个随机值,或者使用更高级的算法分散失效时间。
- 2)构建多个redis实例,个别节点挂了还有别的可以用。
- 3)多级缓存:比如增加本地缓存,减小redis压力。
- 4)对存储层增加限流措施,当请求超出限制,提供降级服务(一般就是返回错误即可)
单线程的redis为什么这么快
- (一)纯内存操作
- (二)单线程操作,避免了频繁的上下文切换
- (三)采用了非阻塞I/O多路复用机制
31、redis采用的删除策略
redis采用的是定期删除+惰性删除策略。
为什么不用定时删除策略?
定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略.
定期删除+惰性删除是如何工作的呢?
定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。
于是,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。
32、为什么Redis的操作是原子性的,怎么保证原子性的?
对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。
Redis的操作之所以是原子性的,是因为Redis是单线程的。
Redis本身提供的所有API都是原子操作,Redis中的事务其实是要保证批量操作的原子性。
33、多个命令在并发中也是原子性的吗?
不一定, 将get和set改成单命令操作,incr 。使用Redis的事务,或者使用Redis+Lua==的方式实现.
34、消息队列
不要使用redis去做消息队列,这不是redis的设计目标。但实在太多人使用redis去做去消息队列,redis的作者看不下去。
35、从目录直接进入redis
redis-cli -h 47.100.56.223 -p 6379
## 36、Redis 主从复制
Redis支持集群功能,为了保证单一节点可用性,redis支持主从复制功能,每个节点有n个复制品(replica),其中一个复制品是master,另外N-1个是从(slave),也就是说Redis支持一主多从。
一个主可以有多个从,而一个从又可以看成主,它还可以有多个从
主从复制优点:
增加单一节点的健壮性,从而提升整个集群的稳定性,(Redis中超过1/2节点不可用时,整个集群不可以用),从节点可以对主节点数据备份,提升容灾能力
读写分离,在Redis主从中,主节点一般用作写(具备读的能力),从节点只能读,利用这个特性实现读写分离,写用主,读用从。