乐趣区

PHP面试常考内容之Memcache和Redis(3)

你好,是我琉忆。今天是周五了,再上一天班就周末了,提前祝大家周末愉快。嘿嘿。这篇文章是本周 Memcache 和 Redis 内存数据库常考的专题。本周一和周三更新的文章路径:PHP 面试常考内容之 Memcache 和 Redis(1)PHP 面试常考内容之 Memcache 和 Redis(2)本周(2019.2-18 至 2 -22)的文章内容点为以下几点,更新时间为每周一三五,可以关注本栏持续关注,感谢你的支持。

一、什么是 Memcache?二、Memcache 有什么特征?三、Memcache 的内存管理机制是什么样的?四、Memcache 和 Memcached 有什么区别?五、如何操作 Memcache?六、如何使用 Memcache 做 Session 共享?七、什么是 Redis?八、如何使用 Redis?九、使用 Redis 需要注意哪些问题?十、新增:Redis 和 Memcache 有什么不同?十一、新增:Redis 如何实现持久化?十二、Memcache 和 Redis 常考的面试题

本章节的内容将会被分为三篇文章进行讲解完整块内容,第一篇主要讲解一到六,第二篇主要讲解七到十一(新增了十和十一),第三篇围绕第十二点。
自己整理了一篇“PHP 不同等级面试都问什么?”的文章,关注公众号:“琉忆编程库”,回复:“等级”,我发给你。
以下正文的部分内容来自《PHP 程序员面试笔试真题解析》书籍,如果转载请保留出处:

十二、Memcache 和 Redis 常考的面试题
【真题 1】Memcache 的工作原理是什么?
答案:Memcache 的工作就是在专门的机器内存里维护一张巨大的 hash 表,存储经常被读写的一些文件与数据,从而极大地提高网站的运行效率。Memcache 的程序运行在一个或多个服务器中,Memcache 把全部的数据保存在内存中,通过 hash 表的方式,每条数据由 key/value 的形式构成,随时接受客户端的请求,然后返回结果。
客户端与 Memcache 建立连接后,存储对象主要是通过唯一的 key 存储 value 到内存中,取数据时通过这个 key 从内存中获取对应的 value。由于 Memcache 的数据是存储在内存中而不是保存在 cache 文件中,所以 Memcache 访问比较快,但是由于这些数据不是永久化存储,所以不建议存储重要数据在 Memcache 中,因为重启服务器后这些数据就会消失。

【真题 2】Memcache 的优点有哪些?
答案:Memcache 是一个高性能的分布式内存对象缓存系统,主要通过在内存里维护一个巨大的 hash 表进行数据缓存。它主要是将数据存储到内存中,然后从内存中读取数据,从而提高读取速度。它主要通过 key-value 的形式存储各种数据,包括图像、视频、文件等。它具有以下几点优点:
(1)支持多台服务器使用 Memcache,由于 Memcache 的存储数据大小必须小于内存的大小,所以可以将 Memcache 使用在多台服务器上,增加缓存容量;
(2)支持均衡请求。当使用多台 Memcache 服务器时,可以均衡请求,避免所有请求都进入一台 Memcache 服务器中,避免服务器挂掉而丢失数据;
(3)支持分布式,可以解决缓存本身水平线性扩展的问题和缓存大并发下的自身性能问题,避免缓存的单点故障问题;
(4)支持部分容灾问题,如果多台服务器存储了 Memcache 数据,其中一台 Memcache 服务器挂掉,部分请求还是可以在其它服务器的 Memcache 中命中,为修复挂掉的服务器争取一些时间。

【真题 3】如何合理地使用 Memcache 缓存?如果缓存数据量过大,那么如何部署?(分布式,缓存时间,优化缓存数据)
答案:如果要合理地使用 Memcache 缓存,那么需要注意以下几点内容:
(1)因为 Memcache 支持最大的存储对象大小为 1M,所以当合理使用 Memcache 缓存时,要求不能往 Memcache 存储一个大于 1MB 的数据;
(2)Memcache 存储的所有数据,如果数据大小分布于各种 chunk 大小区间,从 64B 到 1MB 都有,那么会造成内存的极大浪费和 Memcache 的异常。所以需要注意数据大小的分布区间;
(3)key 的长度不能大于 250 个字符;
(4)虚拟主机不允许运行 Memcache 服务,所以不能把 Memcache 部署到虚拟主机中;
(5)因为 Memcache 可以轻松访问到,所以可以运行在不安全的环境中,如果对数据安全要求高,那么需要着重考虑运行环境的安全问题;
(6)因为 Memcache 存储的数据都在内存中,服务器挂掉就会清空内存,所以缓存中的数据尽量是丢失了也不会有太大影响的数据。
如果缓存中的数据量过大,那么可以采取以下的办法:(1)使用 Memcache 服务器集群的方法,首先是将数据安排放在不同的 Memcache 服务器上,可以将不同硬件服务器上的 Memcache 服务器再做成一个数据互相备份的组,避免数据的单点丢失问题;
(2)缓存数据到数据库中,在数据库中先建一张表来说明 Memcache 服务器集群中缓存数据的存放逻辑,然后实现把缓存数据存到数据库中,可以保证数据库和缓存的数据双向存取。

【真题 4】Redis 与 Memcache 有什么区别?
答案:Redis 是一个完全开源免费的高性能 key-value 数据库,具有丰富的数据类型,可以支持数据的持久化,将内存中的数据保存在磁盘中,当重启服务器时可以再次加载使用。
Memcache 是一个高性能的分布式内存对象缓存系统,用于动态的 Web 应用中帮助数据库减轻负担,在内存中缓存数据和对象,减少每次访问数据时对数据库的访问次数,从而提高访问速度。
它们具有以下几点区别:(1)Redis 和 Memcache 的最大区别是,虽然 Memcache 和 Redis 都是将数据存在内存中,是内存数据库,但 Redis 存储时,并不是所有的数据都一直存储在内存中,而 Memcache 存储时,数据都存在内存中;
(2)数据安全问题,由于 memecache 把数据全部存在内存之中,服务器挂掉后,重启服务器数据就会丢失,而 Redis 可以定期保存数据到磁盘中做持久化存储,当需要时可以再加载使用。对于灾难恢复,Memcache 挂掉后,数据不可恢复,但 Redis 数据丢失后可以通过 aof 恢复;
(3)Redis 支持多种数据结构存储,例如 list,set,hash 等数据结构的存储,而 Memcache 主要是在内存中维护一个统一的巨大的 hash 表进行存储数据,只支持简单的 key/value 类型的数据存储,但 Memcache 可以存储图片、视频、文件及数据库检索结果等;
(4)数据备份问题,Redis 支持数据的备份,即 master-slave 模式的数据备份。而 Memcache 不支持数据持久化,所以无法进行数据备份;
(5)在内存使用率上,使用简单的 key-value 存储的话,Memcached 的内存利用率更高,而如果 Redis 采用 hash 结构来做 key-value 存储,由于其组合式的压缩,其内存利用率会高于 Memcached。具体和应用场景、数据特性有关;
(6)在线程上的比较,Memcache 是支持多线程的,而 Redis 只支持单线程,所以 CPU 利用方面 Memcache 优于 Redis;
(7)它们的扩展都需要做集群;实现方式:master-slave、Hash;
(8)数据的读写方面,Redis 和 Memcache 在写入性能上面差别不大,读取性能上面尤其是批量读取性能上 Memcache 更强。

【真题 5】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 层代码要求比较高,考虑部分包括,节点失效后的替代算法方案,数据震荡后的自动脚本恢复,实例的监控,等等。

自己整理了一篇“PHP 不同等级面试都问什么?”的文章,关注公众号:“琉忆编程库”,回复:“等级”,我发给你。

【真题 6】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 的发布 / 订阅功能来建立聊天系统!(不,这是真的,你可以去核实)。
【真题 7】Redis 持久化数据和缓存怎么做扩容?
答案:如果 Redis 被当做缓存使用,使用一致性哈希实现动态扩容缩容。
如果 Redis 被当做一个持久化存储使用,必须使用固定的 keys-to-nodes 映射关系,节点的数量一旦确定不能变化。否则的话 (即 Redis 节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有 Redis 集群可以做到这样。

【真题 8】Redis 回收进程如何工作的?
答案:一个客户端运行了新的命令,添加了新的数据。
Redi 检查内存使用情况,如果大于 maxmemory 的限制, 则根据设定好的策略进行回收。
一个新的命令被执行,等等。
所以我们不断地穿越内存限制的边界,通过不断达到边界然后不断地回收回到边界以下。
如果一个命令的结果导致大量内存被使用(例如很大的集合的交集保存到一个新的键),不用多久内存限制就会被这个内存使用量超越。

【真题 9】都有哪些办法可以降低 Redis 的内存使用情况呢?
答案:如果你使用的是 32 位的 Redis 实例,可以好好利用 Hash,list,sorted set,set 等集合类型数据,因为通常情况下很多小的 Key-Value 可以用更紧凑的方式存放到一起。

【真题 10】你知道有哪些 Redis 分区实现方案?
答案:客户端分区就是在客户端就已经决定数据会被存储到哪个 redis 节点或者从哪个 redis 节点读取。大多数客户端已经实现了客户端分区。
代理分区 意味着客户端将请求发送给代理,然后代理决定去哪个节点写数据或者读数据。代理根据分区规则决定请求哪些 Redis 实例,然后根据 Redis 的响应结果返回给客户端。redis 和 memcached 的一种代理实现就是 Twemproxy
查询路由 (Query routing) 的意思是客户端随机地请求任意一个 redis 实例,然后由 Redis 将请求转发给正确的 Redis 节点。Redis Cluster 实现了一种混合形式的查询路由,但并不是直接将请求从一个 redis 节点转发到另一个 redis 节点,而是在客户端的帮助下直接 redirected 到正确的 redis 节点。

自己根据不同 PHP 不同等级面试时,会问哪些 PHP 常考的知识点整理成了一篇文章自己整理了一篇“PHP 不同等级面试都问什么?”的文章,关注公众号:“琉忆编程库”,回复:“等级”,我发给你。

更多相关面试常考真题可以阅读《PHP 程序员面试笔试真题解析》。
预告:下周(2019.2.25 至 2019.3.1)一三五将更新的主题为:PHP 面试之会话控制、网络协议、相关的面试题。
以上内容摘自《PHP 程序员面试笔试真题解析》书籍,该书已在天猫、京东、当当等电商平台销售。

更多 PHP 相关的面试知识、考题可以关注公众号获取:琉忆编程库

对本文有什么问题或建议都可以进行留言,我将不断完善追求极致,感谢你们的支持。

退出移动版