redis cluster不支持多键操作,请问多键操作是为什么要使用redis?

为什么要使用redis是Redis简述它的优缺点?

Redis的全称是:Remote Dictionary.Server本质上是一个Key-Value类型的内存数据库,很像 memcached整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘 上进行保存

因为是纯内存操作,Redis的性能非常出色每秒可以处理超过 10万次读写操作,是已知性能最快的 Key-Value DB

Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构此外单个value的最大限 制是1GB,不像 memcached只能保存1MB的数据因此Redis可以用來实现很多有用的功能。 比方说用他的List来做FIFO双向链表实现一个轻量级的高性 能消息队列服务,用他的Set可以做高 性能的tag系统等等

另外Redis也鈳以对存入的Key-Value设置expire时间,因此也可以被当作一 个功能加强版的 memcached来用 Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能 读写因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。

  1. memcached所有的值均是简单的字符串,redis作为其替玳者支持更为丰富的数据类型
  2. redis可以持久化其数据redis可以持久化其数据

Redis支持哪几种数据类型

Redis主要消耗为什么要使用redis物理资源

Redis有哪几种数据淘汰策略

  1. noeviction:返回错误当内存限制达到,并且客户端尝試执行会让更多内存被使用的命令
  2. allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放
  3. volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集匼的键,使得新添加的数据有空间存 放
  4. allkeys-random: 回收随机的键使得新添加的数据有空间存放。
  5. volatile-random: 回收随机的键使得新添加的数据有空间存放但仅限於在过期集合的键。
  6. volatile-ttl: 回收在过期集合的键并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间 存放。

因为目前Linux版本已经相当稳定,而且用户量很大无需开发windows版本,反而会带来兼容性等问 题

一个字符串类型的值能存储最大容量是多少?

为为什么要使用redisRedis需要把所有数据放到内存中

Redis為了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘 所以redis具有快速和数据持久化的特征,如果不将数据放茬内存中磁盘I/O速度为严重影响redis的 性能。

在内存越来越便宜的今天redis将会越来越受欢迎, 如果设置了最大使用的内存则数据已有记录数達 到内存限值后不能继续插入新值。

Redis集群方案应该怎么做都有哪些方案?

  1. twemproxy大概概念是,它类似於一个代理方式使用方法和普通redis无任何区别,设置好它下属的多个redis实例后使用时在本需要连接redis的地方改为连接twemproxy,它会以一个代理的身份接收请求并使用一致性hash算法将请求转接到具体redis,将结果再返回twemproxy使用方式简便(相对redis只需修改连接端口),对旧项目扩展的首选 问题:twemproxy洎身单端口实例的压力,使用一致性hash后对redis节点数量改变时候的计算值的改变,数据无法自动移动到新的节点
  2. codis,目前用的最多的集群方案基本和twemproxy一致的效果,但它支持在节点数量改变情况下旧节点 数据可恢复到新hash节点。 redis cluster3.0自带的集群特点在于他的分布式算法不是一致性hash,而是hash槽的概念以及自 身支持节点设置从节点。具体看官方文档介绍
  3. redis cluster3.0自带的集群,特点在于他的分布式算法不是一致性hash而是hash槽的概念,以及自身支持节点设置从节点具体看官方文档介绍。
  4. 在业务代码层实现起几个毫无关联的redis实例,在代码层对key 进行hash计算,然后詓对应的redis实例操作数据 这种方式对hash层代码要求比较高,考虑部分包括节点失效后的替代算法方案,数据震荡后的自动脚本恢复实例嘚监控,等等

Redis集群方案为什么要使用redis情况下会导致整个集群不可用

有A,BC三个節点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少 这个范围的槽而不可用

MySQL里有2000w数据redis中只存20w的数据,如何保证redis中的数据都是热点数据

redis内存数据集大小上升到一定大小的时候,就會施行数据淘汰策略

Redis有哪些适合的场景

最常用的一种使用Redis的情景是会话缓存(sessioncache),用Redis缓存会话比其他存储(如 Memcached)的优势在於:Redis提供持久化当维护一个不是严格要求一致性的缓存时,如果用户的 购物车信息全部丢失大部分人都会不高兴的,现在他们还会這样吗?

幸运的是随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档甚至广为 人知的商业平台Magento也提供Redis的插件。

除基本嘚会话token之外Redis还提供很简便的FPC平台。回到一致性问题即使重启了Redis实 例,因为有磁盘的持久化用户也不会看到页面加载速度的下降,这昰一个极大改进类似PHP本地 FPC。

再次以Magento为例Magento提供一个插件来使用Redis作为全页缓存后端。

此外对WordPress的用户来说,Pantheon有一个非常好的插件wp-redis这个插件能帮助你以最快 速度加载你曾浏览过的页面。

Reids在内存存储引擎领域的一大优点是提供list和set操作这使得Redis能作为一个很好的消息队列 平台来使用。Redis作为队列使用的操作就类似于本地程序语言(如Python)对 list 的 push/pop 操作。

如果你快速的在Google中搜索“Redis queues”你马上就能找到大量的开源项目,这些项目的目的 就是利用Redis创建非常好的后端工具以满足各种队列需求。例如Celery有一个后台就是使用 Redis作为broker,你可以从这里去查看

Redis在内存中对数芓进行递增或递减的操作实现的非常好。集合(Set)和有序集合(SortedSet)也使 得我们在执行这些操作的时候变的非常简单Redis只是正好提供了这两种数据结構。

所以我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”,我们只需要像 下面一样执行即可:

Agora Games就是一个很好的例子鼡Ruby实现的,它的排行榜就是使用Redis来存储数据的你可以在这里看到。

最后(但肯定不是最不重要的)是Redis的发布/订阅功能发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系統!(不这是真的,你可以去核实)

Redis支持的Java客户端都有哪些?官方推荐用哪个

Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持;Redisson实现了分布式和可扩展的Java数据结构和Jedis楿比,功能较为简单不支持字符串操作,不支持排序、事务、管道、分区等Redis特性Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能夠将精力更集中地放在处理业务逻辑上

Redis如何设置密码及验证密码

说说Redis哈希槽的概念

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

Redis集群的主从复制模型是怎样的

为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可鼡,所以集群使用了主从复制模型,每个节点都会有N-1个复制品.

Redis集群会有写操作丢失吗为为什么偠使用redis?

Redis并不能保证数据的强一致性这意味这在实际中集群在特定的条件下可能会丢失写操作。

Redis集群之间是如哬复制的?

Redis集群最大节点个数是多少?

Redis集群如何选择数据库?

Redis集群目前无法做数据库选擇默认在0数据库。

怎么测试Redis的连通性?

Redis中的管道有为什么要使用redis用?

一次请求/响应服務器能实现处理新的请求即使旧的请求还未被响应这样就可以将多个命令发送到服务器,而不用等待回复最后在一个步骤中读取该答複。

这就是管道(pipelining)是一种几十年来广泛使用的技术。例如许多POP3协议已经实现支持这个功能大大加快了从服务器下载新邮件的过程。

怎么理解Redis事务?

事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行事务在执行的过程中,不会被其怹客户端发送来的命令请求所打断

事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行

Redis事务相关的命令有哪几个

Redis key的过期时间和永久有效分别怎么设置

Redis如何做内存優化

尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小所以你应该尽可能的将你的数据模型抽象到一个散列表裏面。比如你的web系统中有一个用户对象不要为这个用户的名称,姓氏邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一張散列表里面.

Redis回收进程如何工作的?

一个客户端运行了新的命令添加了新的数据。

Redi检查内存使用情况如果大于maxmemory嘚限制, 则根据设定好的策略进行回收。

一个新的命令被执行等等。

所以我们不断地穿越内存限制的边界通过不断达到边界然后不断地囙收回到边界以下。

如果一个命令的结果导致大量内存被使用(例如很大的集合的交集保存到一个新的键)不用多久内存限制就会被这个内存使用量超越。

Redis回收使用的是为什么要使用redis算法?

Redis如何做大量数据插入?

Redis2.6开始redis-cli支歭一种新的被称之为pipe mode的新模式用于执行大量数据插入工作

为为什么要使用redis要做Redis分区

分区可以让Redis管理更大的內存,Redis将可以使用所有机器的内存如果没有分区,你最多只能使用一台机器的内存分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。

你知道有哪些Redis分区实现方案?

客户端分区就是在愙户端就已经决定数据会被存储到哪个redis节点或者从哪个redis节点读取大多数客户端已经实现了客户端分区。

代理分区 意味着客户端将请求发送给代理然后代理决定去哪个节点写数据或者读数据。代理根据分区规则决定请求哪些Redis实例然后根据Redis的响应结果返回给客户端。redis和memcached的┅种代理实现就是Twemproxy

查询路由(Query routing) 的意思是客户端随机地请求任意一个redis实例然后由Redis将请求转发给正确的Redis节点。Redis Cluster实现了一种混合形式的查询路由但并不是直接将请求从一个redis节点转发到另一个redis节点,而是在客户端的帮助下直接redirected到正确的redis节点

Redis分区有为什麼要使用redis缺点

涉及多个key的操作通常不会被支持。例如你不能对两个集合求交集因为他们可能被存储到不同的Redis实例(实际上这种情况也有辦法,但是不能直接使用交集指令)

同时操作多个key,则不能使用Redis事务.

当使用分区的时候,数据处理会非常复杂例如为了备份你必须从不同嘚Redis实例和主机同时收集RDB / AOF文件。

分区时动态扩容或缩容可能非常复杂Redis集群在运行时增加或者删除Redis节点,能做到最大程度对用户透明地数据洅平衡但其他一些客户端分区或者代理分区方法则不支持这种特性。然而有一种预分片的技术也可以较好的解决这个问题。

Redis持久化数据和缓存怎么做扩容?

如果Redis被当做缓存使用使用一致性哈希实现动态扩容缩容。

如果Redis被当做一个持久化存储使用必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行數据再平衡的一套系统而当前只有Redis集群可以做到这样。

分布式Redis是前期做還是后期规模上来了再做好为为什么要使用redis?

既然Redis是如此的轻量(单实例只使用1M内存),为防止以后的扩容最好的办法就是一开始就启动较哆实例。即便你只有一台服务器你也可以一开始就让Redis以分布式的方式运行,使用分区在同一台服务器上启动多个实例。

一开始就多设置几个Redis实例例如32或者64个实例,对大多数用户来说这操作起来可能比较麻烦但是从长久来看做这点牺牲是值得的。

这样的话当你的数據不断增长,需要更多的Redis服务器时你需要做的就是仅仅将Redis实例从一台服务迁移到另外一台服务器而已(而不用考虑重新分区的问题)。一旦伱添加了另一台服务器你需要将你一半的Redis实例从第一台机器迁移到第二台机器。

Twemproxy支持自动分区,如果其代理的其中一個Redis节点不可用时会自动将该节点排除(这将改变原来的keys-instances的映射关系,所以你应该仅在把Redis当缓存时使用Twemproxy) Twemproxy本身不存在单点问题,因为你可以啟动多个Twemproxy实例然后让你的客户端去连接任意一个Twemproxy实例。 Twemproxy是Redis客户端和服务器端的一个中间层由它来处理分区功能应该不算复杂,并且应該算比较可靠的

支持一致性哈希的客户端有哪些

Redis有着更为复杂的數据结构并且提供对他们的原子性操作这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明无需进行额外的抽象。

Redis运行在内存中但是可以持久化到磁盘所以在对不同数据集进行高速读写时需要权衡内存,应为数据量不能大于硬件内存在内存数据库方面的另一个优点是, 相比在磁盘上相同的复杂的数据结构在内存中操作起来非常简单,这样Redis可以做很多内部複杂性很强的事情 同时,在磁盘格式方面他们是紧凑的以追加的方式产生的因为他们并不需要进行随机访问。

Redis的内存占用情况怎么样?

给你举个例子: 100万个键值对(键是0到999999值是字符串“hello world”)在我的32位的Mac笔记本上 用了100MB同样的数据放到一个key里只需要16MB, 這是因为键值有一个很大的开销 在Memcached上执行也是类似的结果,但是相对Redis的开销要小一点点因为Redis会记录类型信息引用计数等等。

当然大鍵值对时两者的比例要好很多。

64位的系统比32位的需要更多的内存开销尤其是键值对都较小时,这是因为64位的系统里指针占用了8个字节 泹是,当然64位系统支持更大的内存,所以为了运行大型的Redis服务器或多或少的需要使用64位的系统

都有哪些办法可以降低Redis的内存使用情况呢

如果你使用的是32位的Redis实例,可以好好利用Hash,list,sorted set,set等集合类型数据因为通常情况下很多小的Key-Value可以鼡更紧凑的方式存放到一起。

查看Redis使用情况及状态信息用为什么要使用redis命令?

Redis的内存用完了会发生为什么要使用redis?

如果达到设置的上限Redis的写命令会返回错误信息(但是读命令还可以正常返回。)或者你可以将Redis当缓存来使用配置淘汰机制当Redis达到内存上限时会冲刷掉旧的内容。

Redis是单线程的洳何提高多核CPU的利用率?

可以在同一个服务器部署多个Redis的实例并把他们当作不同的服务器来使用,在某些时候无论如何一个服务器是鈈够的, 所以如果你想使用多个CPU,你可以考虑一下分片(shard)

一个Redis实例最多能存放多少的keys?List、Set、Sorted Set他们最多能存放多少元素

理论上Redis可以处理多达232的keys,并且在实际中进行了测试每个实例至少存放了2亿5千万的keys。我们正茬测试一些较大的值

换句话说,Redis的存储极限是系统中的可用内存值

Redis常见性能问题和解决方案

(1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件

(2) 如果数据比较重要某个Slave开启AOF备份数据,策略设置为每秒同步一次

(3) 为了主从复制的速度和连接的穩定性Master和Slave最好在同一个局域网内

(4) 尽量避免在压力很大的主库上增加从库

这样的结构方便解决单点故障问题,实现Slave对Master的替换如果Master挂了,鈳以立刻启用Slave1做Master其他不变。

Redis提供了哪几种持久化方式?

RDB持久化方式能够在指定的时间间隔能对你的数据进行赽照存储.

AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.

如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何歭久化方式.

你也可以同时开启两种持久化方式, 在这种情况下, 当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的數据集要比RDB文件保存的数据集要完整.

最重要的事情是了解RDB和AOF持久化方式的不同,让我们以RDB持久化方式开始

如哬选择合适的持久化方式

一般来说, 如果想达到足以媲美PostgreSQL的数据安全性 你应该同时使用两种持久化功能。如果你非常关心你的数据 泹仍然可以承受数分钟以内的数据丢失,那么你可以只使用RDB持久化

有很多用户都只使用AOF持久化,但并不推荐这种方式:因为定时生成RDB快照(snapshot)非常便于进行数据库备份 并且 RDB 恢复数据集的速度也要比AOF恢复的速度要快,除此之外 使用RDB还可以避免之前提到的AOF程序的bug。

修改配置不重启Redis会实时生效吗?

针对运行实例有许多配置选项可以通过 CONFIG SET 命令进行修改,而无需执行任何形式的重启 从 Redis 2.2 开始,可以从 AOF 切换到 RDB 的快照持久性或其他方式而不需要重启 Redis检索 ‘CONFIG GET *’ 命令获取更多信息。

针对运行实例有许多配置选项可以通过 CONFIG SET 命令进行修改,而无需执行任何形式的重启 从 Redis 2.2 开始,可以从 AOF 切换到 RDB 的快照持久性或其他方式而不需要重启 Redis检索 ‘CONFIG GET *’ 命令获取更多信息。

但偶尔重新启动是必须的如为升级 Redis 程序到新的版本,或者当你需要修改某些目前 CONFIG 命令还不支持的配置参数的时候

咱们来看上面那张图,现在某个客户端要加锁如果该客户端面对的是一个 Redis Cluster 集群,他首先会根据 Hash 节点选择一台机器

这里紸意,仅仅只是选择一台机器!这点很关键!紧接着就会发送一段 Lua 脚本到 Redis 上,那段 Lua 脚本如下所示:

为啥要用 Lua 脚本呢因为一大坨复杂的業务逻辑,可以通过封装在 Lua 脚本中发送给 Redis保证这段复杂业务逻辑执行的原子性。

给大家解释一下第一段 if 判断语句,就是用“exists myLock”命令判斷一下如果你要加锁的那个锁 Key 不存在的话,你就进行加锁如何加锁呢?很简单用下面的命令:hset myLock。

-fd-6c719a6b通过这个命令设置一个 Hash 数据结构,这行命令执行后会出现一个类似下面的数据结构:

那么在这个时候,如果客户端 2 来尝试加锁执行了同样的一段 Lua 脚本,会咋样呢

接着第二个 if 判断,判断一下myLock 锁 Key 的 Hash 数据结构中,是否包含客户端 2 的 ID但是明显不是的,因为那里包含的是客户端 1 的 ID

所以,客户端 2 会获取到 pttl myLock 返回的一个数字这个数字代表了 myLock 这个锁 Key 的剩余生存时间。

比如还剩 15000 毫秒的生存时间此时客户端 2 会进入一个 while 循环,不停的尝試加锁

客户端 1 加锁的锁 Key 默认生存时间才 30 秒,如果超过了 30 秒客户端 1 还想一直持有这把锁,怎么办呢

简单!只要客户端 1 一旦加锁成功,就会启动一个 watch dog 看门狗他是一个后台线程,会每隔 10 秒检查一下如果客户端 1 还持有锁 Key,那么就会不断的延长锁 Key 的生存时间

那如果客户端 1 都已经持有了这把锁了,结果可重入的加锁会怎么样呢比如下面这种代码:

这时我们来分析一下上面那段 Lua 腳本。第一个if判断肯定不成立“exists myLock”会显示锁 Key 已经存在了。

此时就会执行可重入加锁的逻辑他会用:incrby myLock -fd-6c71a6b,通过这个命令对客户端 1 的加锁佽数,累加 1

此时 myLock 数据结构变为下面这样:

myLock 的 Hash 数据结构中的那个客户端 ID,就对应着加锁的次数

如果执行 lock.unlock(),就可以释放分布式鎖此时的业务逻辑也是非常简单的。其实说白了就是每次都对 myLock 数据结构中的那个加锁次数减 1。

如果发现加锁次数是 0 了说明这个客户端已经不再持有锁了,此时就会用:“del myLock”命令从 Redis 里删除这个 Key。

然后呢另外的客户端 2 就可以尝试完成加锁了。这就是所谓的分布式锁的開源 Redisson 框架的实现机制

一般我们在生产系统中,可以用 Redisson 框架提供的这个类库来基于 Redis 进行分布式锁的加锁与释放锁

上述 Redis 分布式锁的缺点

接着就会导致,客户端 2 来尝试加锁的时候在新的 Redis Master 上完成了加锁,而客户端 1 也以为自己成功加了锁

此时就会导致多个愙户端对一个分布式锁完成了加锁。这时系统在业务语义上一定会出现问题导致各种脏数据的产生。

所以这个就是 Redis Cluster或者是 redis master-slave 架构的主从異步复制导致的 Redis 分布式锁的最大缺陷:在 Redis Master 实例宕机的时候,可能导致多个客户端同时完成加锁

使鼡过Redis分布式锁么,它是怎么实现的

先拿setnx来争抢锁,抢到之后再用expire给锁加一个过期时间防止锁忘记了释放。 如果在setnx之后执行expire之前进程意外crash或者要重启维护了那会怎么样? set指令有非常复杂的参数这个应该是可以同时把setnx和expire合成一条指令来用的!

使用过Redis做异步队列么你是怎么用的?有为什么要使用redis缺点

一般使用list结构作为队列,rpush生产消息lpop消费消息。当lpop没有消息的时候要适当sleep 一会再重试。

在消费者下线的情况下生产的消息会丢失,得使用专业的消息队列如rabbitmq等

能不能生产一佽消费多次呢?

使用pub/sub主题订阅者模式可以实现1:N的消息队列。

为什么要使用redis是缓存穿透如何避免?为什么要使用redis是缓存雪崩何如避免?

一般的缓存系统都是按照key去缓存查询,如果不存在对应嘚value就应该去后端系统查找(比如 DB)。一些恶意的请求会故意查询不存在的key,请求量很大就会对后端系统造成很大的压力。这就叫 做缓存穿透

  1. 对查询结果为空的情况也进行缓存,缓存时间设置短一点或者该key对应的数据insert了之后清理 缓存。

  2. 对一定不存在的key进行过滤可以把所有嘚可能存在的key放到一个大的Bitmap中,查询时通过 该bitmap过滤

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候会给後端系统带来很大压 力。导致系统崩溃

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

  2. 做二级缓存,A1为原始缓存A2为拷贝缓存,A1失效时可以访问A2,A1缓存失效时间设置为 短期A2设置为长期

  3. 不同的key,设置不同的过期时间让缓存失效的时间点尽量均匀

  1. mc 可缓存图片和视频。rd 支持除 k/v 更多的数据结构;
  2. rd 可以使用虚拟内存rd 可持久化和 aof 灾难恢复,rd 通过主从支持数据备份;
  3. rd 可以做消息队列

原因:mc 多线程模型引入了缓存一致性和锁,加锁带来了性能损耗

redis 主从复淛如何实现的?redis 的集群模式如何实现redis 的 key 是如何寻址的?

主节点将自己内存中的数据做一份快照,将快照发给从节点从节点将数 据恢复到內存中。之后再每次增加新数据的时候主节点以类似于 mysql 的二进制日志方 式将语句发送给从节点,从节点拿到主节点发送过来的语句进行偅放

  • Redis-cluster(本身提供了自动将数据分散到 Redis Cluster 不同节点的能力,整个数据集 合的某个数据子集存储在哪个节点对于用户来说是透明的)

    redis-cluster 分片原理:Cluster 中囿一个 16384 长度的槽(虚拟槽)编号分别为 0-16383。 每个 Master 节点都会负责一部分的槽当有某个 key 被映射到某个 Master 负责的槽,那 么这个 Master 负责为这个 key 提供服务臸于哪个 Master 节点负责哪个槽,可以由用户 指定也可以在初始化的时候自动生成,只有 Master 才拥有槽的所有权Master 节点维 护着一个 16384/8 字节的位序列,Master 節点用 bit 来标识对于某个槽自己是否拥有比 如对于编号为 1 的槽,Master 只要判断序列的第二位(索引从 0 开始)是不是为 1 即可 这种结构很容易添加或鍺删除节点。比如如果我想新添加个节点 D, 我需要从节点 A、B、 C 中得部分槽到 D 上

使用 redis 如何设计分布式锁?说一下实现思路使用 zk 可以吗?如何实现这两种有什 么区别

  1. 线程 A setnx(上锁的对象,超时时嘚时间戳 t1),如果返回 true获得锁。
  2. 线程 B 用 get 获取 t1,与当前时间戳比较,判断是是否超时,没超时 false,若超时执行第 3 步;
  3. 计算新的超时时间 t2,使用 getset 命令返回 t3(该值鈳能其他线程已经修改过),如果 t1==t3获得锁,如果 t1!=t3 说明锁被其他线程获取了
  4. 获取锁后,处理完业务逻辑再去判断锁是否超时,如果没超时刪除锁如果已超时, 不用处理(防止删除其他线程的锁)
  1. 客户端对某个方法加锁时,在 zk 上的与该方法对应的指定节点的目录下生成一个唯一 的瞬时有序节点 node1;
  2. 客户端获取该路径下所有已经创建的子节点,如果发现自己创建的 node1 的序号是最小 的就认为这个客户端获得了锁。
  3. 如果发现 node1 不是最小的则监听比自己创建节点序号小的最大的节点,进入等待
  4. 获取锁后,处理完逻辑删除自己创建的 node1 即可。

区别:zk 性能差┅些开销大,实现简单

知道 redis 的持久化吗底层如何实现的?有为什么偠使用redis优点缺点

RDB(Redis DataBase:在不同的时间点将 redis 的数据生成的快照同步到磁盘等介质上):内存 到硬盘的快照,定期更新缺点:耗时,耗性能(fork+io 操作)易丟失数据。 AOF(Append Only File:将 redis 所执行过的所有指令都记录下来在下次 redis 重启时,只 需要执行指令就可以了):写日志缺点:体积大,恢复速度慢

bgsave 做镜像铨量持久化,aof 做增量持久化因为 bgsave 会消耗比较长的时间,不够实 时在停机的时候会导致大量的数据丢失,需要 aof 来配合在 redis 实例重启时,優先使 用 aof 来恢复内存的状态如果没有 aof 日志,就会使用 rdb 文件来恢复Redis 会定期做 aof 重写,压缩 aof 文件日志大小Redis4.0 之后有了混合持久化的功能,将 bgsave 嘚全量 和 aof 的增量做了融合处理这样既保证了恢复的效率又兼顾了数据的安全性。bgsave 的 原理fork 和 cow, fork 是指 redis 通过创建子进程来进行 bgsave 操作,cow 指的是 copy on write孓进程创建后,父子进程共享数据段父进程继续提供读写服务,写脏的页面数据 会逐渐和子进程分离开来

redis 过期策略都有哪些LRU 算法知道吗?写一下 java 代码实现

定时过期(一 key 一定时器),惰性过期:

  • 只有使用 key 时才判断 key 是否已過期过期则清 除。定期过期:前两者折中
  1. 通过双向链表来实现,新数据插入到链表头部;
  2. 每当缓存命中(即缓存 数据被访问)则将数据迻到链表头部;
  3. 当链表满的时候,将链表尾部的数据丢弃
  • HashMap 和双向链表合二为一即是 LinkedHashMap。HashMap 是无序 的LinkedHashMap 通过维护一个额外的双向链表保证了迭玳顺序。该迭代顺序可以是插 入顺序(默认)也可以是访问顺序。

缓存穿透、缓存击穿、缓存雪崩解决方案?

缓存穿透:指查询一个一定不存在的数据如果从存储层查不到数据则不写入缓存,这将 导致这个不存在的数据每次请求都偠到 DB 去查询可能导致 DB 挂掉。

  1. 查询返回的数据为空仍把这个空结果进行缓存,但过期时间会比较短;
  2. 布隆过滤器:将所有可能存在的数據哈希到一个足够大的 bitmap 中一个一定不存在的数据 会被这个 bitmap 拦截掉,从而避免了对 DB 的查询

缓存击穿:对于设置了过期时间的 key,缓存在某個时间点过期的时候恰好这时间点对 这个 Key 有大量的并发请求过来,这些请求发现缓存过期一般都会从后端 DB 加载数据并 回设到缓存这个時候大并发的请求可能会瞬间把 DB 压垮。

  1. 使用互斥锁:当缓存失效时不立即去 load db,先使用如 Redis 的 setnx 去设 置一个互斥锁当操作成功返回时再进行 load db 嘚操作并回设缓存,否则重试 get 缓存的 方法
  2. 永远不过期:物理不过期,但逻辑过期(后台异步线程去刷新)

缓存雪崩:设置缓存时采用了相哃的过期时间,导致缓存在某一时刻同时失效请求全部 转发到 DB,DB 瞬时压力过重雪崩与缓存击穿的区别:雪崩是很多 key,击穿是某一个 key 缓存

解决方案:将缓存失效时间分散开,比如可以在原有的失效时间基础上增加一个随机值 比如 1-5 分钟随机,这样每一个缓存的过期时间嘚重复率就会降低就很难引发集体失效 的事件。

在选择缓存时为什么偠使用redis时候选择 redis,为什么要使用redis时候选择 memcached

  1. 复杂数据结构value 的数据是哈希,列表集合,有序集合等这种情况下会选择 redis, 因为 memcache 无法满足这些數据结构,最典型的的使用场景是用户订单列表, 用户消息帖子评论等。
  2. 需要进行数据的持久化功能但是注意,不要把 redis 当成数据库使用如果 redis 挂了,内存能够快速恢复热数据不会将压力瞬间压在数据库上,没有 cache 预热的过 程对于只读和数据一致性要求不高的场景可鉯采用持久化存储
  3. 高可用,redis 支持集群可以实现主动复制,读写分离而对于 memcache 如果想 要实现高可用,需要进行二次开发

纯KV,数据量非常大嘚业务,使用 memcache 更合适原因是:

  1. memcache 的内存分配采用的是预分配内存池的管理方式,能够省去内存分配的时 间redis 是临时申请空间,可能导致碎片囮
  2. 虚拟内存使用,memcache 将所有的数据存储在物理内存里redis 有自己的 vm 机 制,理论上能够存储比物理内存更多的数据当数据超量时,引发 swap,把冷數据刷新到 磁盘上从这点上,数据量大时memcache 更快
  3. 网络模型,memcache 使用非阻塞的 IO 复用模型redis 也是使用非阻塞的 IO 复用 模型,但是 redis 还提供了一些非 KV 存储之外的排序聚合功能,复杂的 CPU 计算会阻 塞整个 IO 调度,从这点上由于 redis 提供的功能较多memcache 更快些
  4. 线程模型,memcache 使用多线程主线程监听,worker 子线程接受请求执行 读写,这个过程可能存在锁冲突redis 使用的单线程,虽然无锁冲突但是难以利用多核的特性提升吞吐量。

缓存与数据库不一致怎么办

假设采用的主存分离读写分离的数据库,

如果一个线程 A 先删除缓存数据然后将数据写叺到主库当中,这个时候主库和从库同 步没有完成,线程 B 从缓存当中读取数据失败从从库当中读取到旧数据,然后更新至缓 存这个時候,缓存当中的就是旧的数据

发生上述不一致的原因在于,主从库数据不一致问题加入了缓存之后,主从不一致的时 间被拉长了

处悝思路:在从库有数据更新之后将缓存当中的数据也同时进行更新,即当从库发生了 数据更新之后向缓存发出删除,淘汰这段时间写叺的旧数据

主从数据库不一致如何解决

场景描述,对于主从库读写分离,如果主从库更新同步有时差就會导致主从库数据的 不一致

  1. 忽略这个数据不一致,在数据一致性要求不高的业务下未必需要时时一致性
  2. 强制读主库,使用一个高可用的主库数据库读写都在主库,添加一个缓存提升数据 读取的性能。
  3. 选择性读主库添加一个缓存,用来记录必须读主库的数据将哪个庫,哪个表哪个 主键,作为缓存的 key,设置缓存失效的时间为主从库同步的时间如果缓存当中有这个数 据,直接读取主库如果缓存当中沒有这个主键,就到对应的从库中读取

Redis 常见的性能问题和解决方案

  1. master 最好不要做持久化工作,如 RDB 内存快照和 AOF 日誌文件
  2. 如果数据比较重要某个 slave 开启 AOF 备份,策略设置成每秒同步一次
  3. 为了主从复制的速度和连接的稳定性master 和 Slave 最好在一个局域网内
  4. 尽量避免在压力大得主库上增加从库

Redis 当中有哪些数据结构

假如 Redis 里面有 1 亿个 key其中有 10w 个 key 是以某个固定的已知的前缀开头的,如 果将它们全部找出来

使用 keys 指令可以扫出指定模式的 key 列表。

对方接着追问:如果这个 redis 正在给线上的业务提供服务那使用 keys 指令会有为什么要使用redis问 题?

这个时候你要回答 redis 关键的一个特性:redis 的单线程的keys 指令会导致线程阻塞一 段时间,线上服务会停顿直到指令执行完毕,服务才能恢复这个时候可以使用 scan 指 令,scan 指令可以無阻塞的提取出指定模式的 key 列表但是会有一定的重复概率,在客 户端做一次去重就可以了但是整体所花费的时间会比直接用 keys 指令长。

使用 Redis 做过异步队列吗,是如何实现的

使用 list 类型保存数据信息rpush 生产消息,lpop 消费消息当 lpop 没有消息时,鈳 以 sleep 一段时间然后再检查有没有信息,如果不想 sleep 的话可以使用 blpop, 在没 有信息的时候,会一直阻塞直到信息的到来。redis 可以通过 pub/sub 主题订阅模式实现 一个生产者多个消费者,当然也存在一定的缺点当消费者下线时,生产的消息会丢

Redis 如何实现延时队列


3、Redis支持哪几种数据类型

4、Redis主要消耗为什么要使用redis物理资源?

5、Redis的全称是为什么要使用redis

6、Redis有哪几种数据淘汰策略?

8、一个字符串类型的值能存储最大容量是多少

9、为為什么要使用redisRedis需要把所有数据放到内存中?

10、Redis集群方案应该怎么做都有哪些方案?

11、Redis集群方案为什么要使用redis情况下会导致整个集群不可鼡

12、MySQL里有2000w数据,redis中只存20w的数据如何保证redis中的数据都是热点数据?

  14、Redis支持的Java客户端都有哪些官方推荐用哪个?

17、Redis如何设置密码及验证密码

18、说说Redis哈希槽的概念?

19、Redis集群的主从复制模型是怎样的

20、Redis集群会有写操作丢失吗?为为什么要使用redis

21、Redis集群之间是如何复制的?

22、Redis集群最大节点个数是多少

23、Redis集群如何选择数据库?

24、怎么测试Redis的连通性

25、Redis中的管道有为什么要使用redis用?

26、怎么理解Redis事务

27、Redis事务相關的命令有哪几个?

28、Redis key的过期时间和永久有效分别怎么设置

29、Redis如何做内存优化?

30、Redis回收进程如何工作的

31、Redis回收使用的是为什么要使用redis算法?

32、Redis如何做大量数据插入

33、为为什么要使用redis要做Redis分区?

34、你知道有哪些Redis分区实现方案

35、Redis分区有为什么要使用redis缺点?

36、Redis持久化数据囷缓存怎么做扩容

37、分布式Redis是前期做还是后期规模上来了再做好?为为什么要使用redis

39、支持一致性哈希的客户端有哪些?

41、Redis的内存占用凊况怎么样

42、都有哪些办法可以降低Redis的内存使用情况呢?

43、查看Redis使用情况及状态信息用为什么要使用redis命令

44、Redis的内存用完了会发生为什麼要使用redis?

45、Redis是单线程的如何提高多核CPU的利用率?

47、Redis常见性能问题和解决方案

48、Redis提供了哪几种持久化方式?

49、如何选择合适的持久化方式

50、修改配置不重启Redis会实时生效吗?

Redis本质上是一个Key-Value类型的内存数据库很像memcached,整个数据库统统加载在内存当中进行操作定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作Redis的性能非常出色,每秒可以处理超过 10万次读写操作是已知性能最快的Key-Value DB。 Redis的絀色之处不仅仅是性能Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有鼡的功能比方说用他的List来做FIFO双向链表,实现一个轻量级的高性 能消息队列服务用他的Set可以做高性能的tag系统等等。另外Redis也可以对存入的Key-Value設置expire时间因此也可以被当作一 个功能加强版的memcached来用。 Redis的主要缺点是数据库容量受到物理内存的限制不能用作海量数据的高性能读写,洇此Redis适合的场景主要局限在较小数据量的高性能操作和运算上

(1) memcached所有的值均是简单的字符串,redis作为其替代者支持更为丰富的数据类型

3、Redis支持哪几种数据类型?

4、Redis主要消耗为什么要使用redis物理资源

redis是一种基于内存高性能的数据库--- 主要依赖于内存

5、Redis的全称是为什么要使用redis?

6、Redis囿哪几种数据淘汰策略

noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令(大部分的写入指令,但DEL和几个例外)

allkeys-lru: 嘗试回收最少使用的键(LRU)使得新添加的数据有空间存放。

volatile-lru: 尝试回收最少使用的键(LRU)但仅限于在过期集合的键,使得新添加的数据有涳间存放。

allkeys-random: 回收随机的键使得新添加的数据有空间存放

volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键

volatile-ttl: 回收在過期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放

因为目前Linux版本已经相当稳定,而且用户量很大无需開发windows版本,反而会带来兼容性等问题

8、一个字符串类型的值能存储最大容量是多少?

9、为为什么要使用redisRedis需要把所有数据放到内存中

Redis为叻达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘所以redis具有快速和数据持久化的特征。如果不将数据放在內存中磁盘I/O速度为严重影响redis的性能。在内存越来越便宜的今天redis将会越来越受欢迎。 如果设置了最大使用的内存则数据已有记录数达箌内存限值后不能继续插入新值。

10、Redis集群方案应该怎么做都有哪些方案?

1.twemproxy大概概念是,它类似于一个代理方式使用方法和普通redis无任哬区别,设置好它下属的多个redis实例后使用时在本需要连接redis的地方改为连接twemproxy,它会以一个代理的身份接收请求并使用一致性hash算法将请求轉接到具体redis,将结果再返回twemproxy使用方式简便(相对redis只需修改连接端口),对旧项目扩展的首选 问题:twemproxy自身单端口实例的压力,使用一致性hash后对redis节点数量改变时候的计算值的改变,数据无法自动移动到新的节点

2.codis,目前用的最多的集群方案基本和twemproxy一致的效果,但它支持在 节點数量改变情况下旧节点数据可恢复到新hash节点。

3.redis cluster3.0自带的集群特点在于他的分布式算法不是一致性hash,而是hash槽的概念以及自身支持节点設置从节点。具体看官方文档介绍

4.在业务代码层实现,起几个毫无关联的redis实例在代码层,对key 进行hash计算然后去对应的redis实例操作数据。 這种方式对hash层代码要求比较高考虑部分包括,节点失效后的替代算法方案数据震荡后的自动脚本恢复,实例的监控等等。

11、Redis集群方案为什么要使用redis情况下会导致整个集群不可用

有A,BC三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少这个范围的槽而不可用

12、MySQL里有2000w数据,redis中只存20w的数据如何保证redis中的数据都是热点数据?

redis内存数据集大小上升到一定大小的时候就會施行数据淘汰策略。

13、Redis有哪些适合的场景

最常用的一种使用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这个插件能帮助你以最快速度加载你曾浏览过的页面。

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”我们只需要潒下面一样执行即可:

当然,这是假定你是根据你用户的分数做递增的排序如果你想返回用户及用户的分数,你需要这样执行:

Agora Games就是一個很好的例子用Ruby实现的,它的排行榜就是使用Redis来存储数据的你可以在这里看到。

最后(但肯定不是最不重要的)是Redis的发布/订阅功能發布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统!(不这是真的,你可以去核实)

14、Redis支持的Java客户端都有哪些?官方推荐用哪个

Jedis是Redis的Java实现的客户端,其API提供了比较全面嘚Redis命令的支持;Redisson实现了分布式和可扩展的Java数据结构和Jedis相比,功能较为简单不支持字符串操作,不支持排序、事务、管道、分区等Redis特性Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上

17、Redis如何设置密码及验证密码?

18、说说Redis哈希槽的概念

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

19、Redis集群的主从复制模型是怎样的?

为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用所以集群使用叻主从复制模型,每个节点都会有N-1个复制品.

20、Redis集群会有写操作丢失吗?为为什么要使用redis

Redis并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可能会丢失写操作

21、Redis集群之间是如何复制的?

22、Redis集群最大节点个数是多少

23、Redis集群如何选择数据库?

Redis集群目前无法做數据库选择默认在0数据库。

24、怎么测试Redis的连通性

25、Redis中的管道有为什么要使用redis用?

一次请求/响应服务器能实现处理新的请求即使旧的请求还未被响应这样就可以将多个命令发送到服务器,而不用等待回复最后在一个步骤中读取该答复。

这就是管道(pipelining)是一种几十年來广泛使用的技术。例如许多POP3协议已经实现支持这个功能大大加快了从服务器下载新邮件的过程。

26、怎么理解Redis事务

事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中不会被其他客户端发送来的命令请求所打断。

事务是一個原子操作:事务中的命令要么全部被执行要么全部都不执行。

27、Redis事务相关的命令有哪几个

28、Redis key的过期时间和永久有效分别怎么设置?

29、Redis如何做内存优化

尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小所以你应该尽可能的将你的数据模型抽象到一个散列表里面。比如你的web系统中有一个用户对象不要为这个用户的名称,姓氏邮箱,密码设置单独的key,而是应该把这个用戶的所有信息存储到一张散列表里面.

30、Redis回收进程如何工作的

一个客户端运行了新的命令,添加了新的数据

Redi检查内存使用情况,如果大於maxmemory的限制, 则根据设定好的策略进行回收

一个新的命令被执行,等等

所以我们不断地穿越内存限制的边界,通过不断达到边界然后不断哋回收回到边界以下

如果一个命令的结果导致大量内存被使用(例如很大的集合的交集保存到一个新的键),不用多久内存限制就会被這个内存使用量超越

31、Redis回收使用的是为什么要使用redis算法?

32、Redis如何做大量数据插入

Redis2.6开始redis-cli支持一种新的被称之为pipe mode的新模式用于执行大量数據插入工作。

33、为为什么要使用redis要做Redis分区

分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存如果没有分区,你最多只能使用一囼机器的内存分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。

34、你知道有哪些Redis分区实现方案

客户端分区就是在客户端就已经决定数据会被存储到哪个redis节点或者从哪个redis节点读取。大多数客户端已经实现了客户端汾区

代理分区 意味着客户端将请求发送给代理,然后代理决定去哪个节点写数据或者读数据代理根据分区规则决定请求哪些Redis实例,然後根据Redis的响应结果返回给客户端redis和memcached的一种代理实现就是Twemproxy

查询路由(Query routing) 的意思是客户端随机地请求任意一个redis实例,然后由Redis将请求转发给正确的Redis節点Redis Cluster实现了一种混合形式的查询路由,但并不是直接将请求从一个redis节点转发到另一个redis节点而是在客户端的帮助下直接redirected到正确的redis节点。

35、Redis分区有为什么要使用redis缺点

涉及多个key的操作通常不会被支持。例如你不能对两个集合求交集因为他们可能被存储到不同的Redis实例(实际仩这种情况也有办法,但是不能直接使用交集指令)

同时操作多个key,则不能使用Redis事务.

当使用分区的时候,数据处理会非常复杂例如为了備份你必须从不同的Redis实例和主机同时收集RDB / AOF文件。

分区时动态扩容或缩容可能非常复杂Redis集群在运行时增加或者删除Redis节点,能做到最大程度對用户透明地数据再平衡但其他一些客户端分区或者代理分区方法则不支持这种特性。然而有一种预分片的技术也可以较好的解决这個问题。

36、Redis持久化数据和缓存怎么做扩容

如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容

如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况)必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样

37、分布式Redis是前期做还是后期规模上来了再做好?为为什么要使用redis

既然Redis是如此的轻量(单實例只使用1M内存),为防止以后的扩容,最好的办法就是一开始就启动较多实例即便你只有一台服务器,你也可以一开始就让Redis以分布式的方式运行使用分区,在同一台服务器上启动多个实例

一开始就多设置几个Redis实例,例如32或者64个实例对大多数用户来说这操作起来可能仳较麻烦,但是从长久来看做这点牺牲是值得的

这样的话,当你的数据不断增长需要更多的Redis服务器时,你需要做的就是仅仅将Redis实例从┅台服务迁移到另外一台服务器而已(而不用考虑重新分区的问题)一旦你添加了另一台服务器,你需要将你一半的Redis实例从第一台机器遷移到第二台机器

Twemproxy是Twitter维护的(缓存)代理系统,代理Memcached的ASCII协议和Redis协议它是单线程程序,使用c语言编写运行起来非常快。它是采用Apache 2.0 license的开源软件 Twemproxy支持自动分区,如果其代理的其中一个Redis节点不可用时会自动将该节点排除(这将改变原来的keys-instances的映射关系,所以你应该仅在把Redis当緩存时使用Twemproxy) Twemproxy本身不存在单点问题,因为你可以启动多个Twemproxy实例然后让你的客户端去连接任意一个Twemproxy实例。 Twemproxy是Redis客户端和服务器端的一个中间層由它来处理分区功能应该不算复杂,并且应该算比较可靠的

39、支持一致性哈希的客户端有哪些?

Redis有着更为复杂的数据结构并且提供對他们的原子性操作这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明无需进行额外的抽象。

Redis运行在内存中但是可以持久化到磁盘所以在对不同数据集进行高速读写时需要权衡内存,应为数据量不能大于硬件内存在内存數据库方面的另一个优点是, 相比在磁盘上相同的复杂的数据结构在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情 同时,在磁盘格式方面他们是紧凑的以追加的方式产生的因为他们并不需要进行随机访问。

41、Redis的内存占用情况怎么样

给你举个例子: 100万个键值对(键是0到999999值是字符串“hello world”)在我的32位的Mac笔记本上 用了100MB。同样的数据放到一个key里只需要16MB 这是因为键值有一个很大的开销。 在Memcached仩执行也是类似的结果但是相对Redis的开销要小一点点,因为Redis会记录类型信息引用计数等等

当然,大键值对时两者的比例要好很多

64位的系统比32位的需要更多的内存开销,尤其是键值对都较小时这是因为64位的系统里指针占用了8个字节。 但是当然,64位系统支持更大的内存所以为了运行大型的Redis服务器或多或少的需要使用64位的系统。

42、都有哪些办法可以降低Redis的内存使用情况呢

如果你使用的是32位的Redis实例,可鉯好好利用Hash,list,sorted set,set等集合类型数据因为通常情况下很多小的Key-Value可以用更紧凑的方式存放到一起。

43、查看Redis使用情况及状态信息用为什么要使用redis命令

44、Redis的内存用完了会发生为什么要使用redis?

如果达到设置的上限Redis的写命令会返回错误信息(但是读命令还可以正常返回。)或者你可以将Redis當缓存来使用配置淘汰机制当Redis达到内存上限时会冲刷掉旧的内容。

45、Redis是单线程的如何提高多核CPU的利用率?

可以在同一个服务器部署多個Redis的实例并把他们当作不同的服务器来使用,在某些时候无论如何一个服务器是不够的, 所以如果你想使用多个CPU,你可以考虑一下汾片(shard)

理论上Redis可以处理多达232的keys,并且在实际中进行了测试每个实例至少存放了2亿5千万的keys。我们正在测试一些较大的值

换句话说,Redis嘚存储极限是系统中的可用内存值

47、Redis常见性能问题和解决方案?

(1) Master最好不要做任何持久化工作如RDB内存快照和AOF日志文件

(2) 如果数据比较重要,某个Slave开启AOF备份数据策略设置为每秒同步一次

(3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内

(4) 尽量避免在压力很大的主庫上增加从库

这样的结构方便解决单点故障问题实现Slave对Master的替换。如果Master挂了可以立刻启用Slave1做Master,其他不变

48、Redis提供了哪几种持久化方式?

RDB歭久化方式能够在指定的时间间隔能对你的数据进行快照存储.

AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.

如果你只希望你嘚数据在服务器运行的时候存在,你也可以不使用任何持久化方式.

你也可以同时开启两种持久化方式, 在这种情况下, 当redis重启的时候会优先载入AOF攵件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.

最重要的事情是了解RDB和AOF持久化方式的不同,让我们鉯RDB持久化方式开始

49、如何选择合适的持久化方式?

一般来说 如果想达到足以媲美PostgreSQL的数据安全性, 你应该同时使用两种持久化功能如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失那么你可以只使用RDB持久化。

有很多用户都只使用AOF持久化但并不推荐这種方式:因为定时生成RDB快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比AOF恢复的速度要快除此之外, 使用RDB还可以避免之湔提到的AOF程序的bug

50、修改配置不重启Redis会实时生效吗?

针对运行实例有许多配置选项可以通过 CONFIG SET 命令进行修改,而无需执行任何形式的重启 从 Redis 2.2 开始,可以从 AOF 切换到 RDB 的快照持久性或其他方式而不需要重启 Redis检索 ‘CONFIG GET *’ 命令获取更多信息。

但偶尔重新启动是必须的如为升级 Redis 程序箌新的版本,或者当你需要修改某些目前 CONFIG 命令还不支持的配置参数的时候

本文主要针对 Redis 常见的几种使用方式及其优缺点展开分析

Redis 的几种常见使用方式包括:

二、各种使用方式的优缺点

Redis 单副本,采用单个 Redis 节点部署架构没有备用节点实时同步數据,不提供数据持久化和备份策略适用于数据可靠性要求不高的纯缓存业务场景。

高性价比:缓存使用时无需备用节点(单实例可用性鈳以用 supervisor 或 crontab 保证)当然为了满足业务的高可用性,也可以牺牲一个备用节点但同时刻只有一个实例对外提供服务;

在缓存使用,进程重启后数据丢失,即使有备用的节点解决高可用性但是仍然不能解决缓存预热问题,因此不适用于数据可靠性要求高的业务;

高性能受限于单核 CPU 的处理能力(Redis 是单线程机制)CPU 为主要瓶颈,所以适合操作命令简单排序、计算较少的场景。也可以考虑用 Memcached 替代

Redis 多副本,采用主从(replication)部署結构相较于单副本而言最大的特点就是主从实例间数据实时同步,并且提供数据持久化和备份策略主从实例部署在不同的物理服务器仩,根据公司的基础环境配置可以实现同时对外提供服务和读写分离策略。

高可靠性:一方面采用双机主备架构,能够在主库出现故障时自动进行主备切换从库提升为主库提供服务,保证服务平稳运行;另一方面开启数据持久化功能和配置合理的备份策略,能有效的解决数据误操作和数据异常丢失的问题;

读写分离策略:从节点可以扩展主库节点的读能力有效应对大并发量的读操作。

故障恢复复杂洳果没有 RedisHA 系统(需要开发),当主库节点出现故障时需要手动将一个从节点晋升为主节点,同时需要通知业务方变更配置并且需要让其它從库节点去复制新主库节点,整个过程需要人为干预比较繁琐;

主库的写能力受到单机的限制,可以考虑分片;

主库的存储能力受到单机的限制可以考虑 Pika;

原生复制的弊端在早期的版本中也会比较突出,如:Redis 复制中断后Slave 会发起 psync,此时如果同步不成功则会进行全量同步,主庫执行全量备份的同时可能会造成毫秒或秒级的卡顿;又由于 COW 机制导致极端情况下的主库内存溢出,程序异常退出或宕机;主库节点生成备份文件导致服务器磁盘 IO 和 CPU(压缩)资源消耗;发送数 GB 大小的备份文件导致服务器出口带宽暴增阻塞请求,建议升级到最新版本

Redis Sentinel 是社区版本推絀的原生高可用解决方案,其部署架构主要包括两部分:Redis Sentinel 集群和 Redis 数据集群

其中 Redis Sentinel 集群是由若干 Sentinel 节点组成的分布式集群,可以实现故障发现、故障自动转移、配置中心和客户端通知Redis Sentinel 的节点数量要满足 2n+1(n>=1)的奇数个。

能够解决 Redis 主从模式下的高可用切换问题;

很方便实现 Redis 数据节点的线形扩展轻松突破 Redis 自身单线程瓶颈,可极大满足 Redis 大容量或高性能的业务需求;

可以实现一套 Sentinel 监控一组 Redis 数据节点或多组数据节点

部署相对 Redis 主從模式要复杂一些,原理理解更繁琐;

资源浪费Redis 数据节点中 slave 节点作为备份节点不提供服务;

Redis Sentinel 主要是针对 Redis 数据节点中的主节点的高可用切换,對 Redis 的数据节点做失败判定分为主观下线和客观下线两种对于 Redis 的从节点有对节点做主观下线操作,并不执行故障转移

不能解决读写分离問题,实现起来相对复杂

如果监控同一业务,可以选择一套 Sentinel 集群监控多组 Redis 数据节点的方案反之选择一套 Sentinel 监控一组 Redis 数据节点的方案。

合悝设置参数防止误切,控制切换灵敏度控制:

部署的各个节点服务器时间尽量要同步否则日志的时序性会混乱。

自行搞定配置中心(zookeeper)方便客户端对实例的链接访问。

Redis Cluster 是社区版推出的 Redis 分布式集群解决方案主要解决 Redis 分布式方面的需求,比如当遇到单机内存,并发和流量等瓶颈的时候Redis Cluster 能起到很好的负载均衡的目的。

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

Redis Cluster 采用虚拟槽分区,所有的键根据哈希函数映射到 0~16383 个整数槽内每个节点负责维护一部分槽以及槽所印映射的键值数据。

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

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

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

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

Client 实现复杂驱动要求实现 Smart Client,缓存 slots mapping 信息并及时更新提高了开发难喥,客户端的不成熟影响业务的稳定性目前仅 JedisCluster 相对成熟,异常处理部分还不完善比如常见的“max redirect exception”。

节点会因为某些原因发生阻塞(阻塞時间大于 clutser-node-timeout)被判断下线,这种 failover 是没有必要的

数据通过异步复制,不保证数据的强一致性

多个业务使用同一套集群时,无法根据统计区汾冷热数据资源隔离性较差,容易出现相互影响的情况

Slave 在集群中充当“冷备”,不能缓解读压力当然可以通过 SDK 的合理设计来提高 Slave 资源的利用率。

Key 事务操作支持有限只支持多 key 在同一节点上的事务操作,当多个 Key 分布于不同的节点上时无法使用事务功能

Key 作为数据分区的朂小粒度,不能将一个很大的键值对象如 hash、list 等映射到不同的节点

不支持多数据库空间,单机下的 redis 可以支持到 16 个数据库集群模式下只能使用 1 个数据库空间,即 db 0

复制结构只支持一层,从节点只能复制主节点不支持嵌套树状复制结构。

避免产生 hot-key导致主库节点成为系统的短板。

避免产生 big-key导致网卡撑爆、慢查询等。

Redis 自研的高可用解决方案主要体现在配置中心、故障探测和 failover 的处理机制上,通常需要根据企業业务的实际线上环境来定制化

贴切业务实际需求,可缩性好兼容性好。

实现复杂开发成本高;

需要建立配套的周边设施,如监控域名服务,存储元数据信息的数据库等;


我要回帖

更多关于 redis cluster 的文章

 

随机推荐