1000道互联网java面试题(五)Memcached 面试题

这本书中间还有个4,是es面试题。仔仔细细读了两遍就劝退我了,分开来每个字都差不多认识,连在一起完全看不明白,而且我也没实践经验,所以就不浪费时间了,直接跳到缓存这里。下面开始一个题一个题整理:

1. Memcached是什么,有什么作用?

首先,Memcached是一个开源的,高性能的内存缓存软件。从名称上看,Mem是内存的意思,cached是缓存、连起来就是内存缓存。
通过在事先规划好的内存空间内临时缓存数据库中的各类数据,以减少业务对数据库的高并发访问。提升数据库的访问性能,加速集群应用的反应能力。
Memcached的应用场景:

  1. 作为数据库的前端缓存应用
    • 完整缓存,静态缓存
      比如商品分类,商品信息。我们可以先放在内存中,再提供前端访问入口。我们把这种先放入内存再访问的,称之为预热。用户访问时可以只读取缓存,而不用访问数据库了。
    • 执点缓存
      即只存热点数据,也就是经常访问的数据。然后我们先预热,存在缓存中,如果缓存中没有再去查询数据库,其实这个我们是经常使用的,一般我们用的Memcached注解版就是这样一个作用。在查询的时候相同的方法参数走缓存查询,缓存中没有去查询数据库,然后存到缓存中并将结果返回。
      当然了这个需要配套的一个功能就是:当数据发生更改时要相应的修改缓存中的数据,或者直接删除等待下次访问再重新查询。

电商秒杀:当如果遇到电商秒杀这种时间短,并发高的场景,一定要事先预热或者采用其他措施来解决。这个其他措施可以是获取资格而不是直接购买。
比如可以在数据库标记0/1.先标记出来再事后去下订单等操作(因为下单是一系列操作。而修改标记只是一个操作)。

2. Memcached服务分布式集群如何实现的?

和mysql不同,Memcached服务每一个都只存一部分数据,这些集群中所有数据加起来才是完整数据。其数据访问有两种方式:

  • 前端实现。通过对key做hash(一致性hash算法)定位到具体的服务器。
  • 负载均衡器。(其本质也是对key做hash,只不过一个是代码实现,一个是现有的工具实现)

一致hash算法不仅仅是为了每次访问只请求一个服务器,同时也是为了当某一台服务器宕机后,缓存服务器的更新重分配比例降到最低。

3. Memcached的服务特点及工作原理是什么?

  • Memcached是完全基于内存缓存的。
  • Memcached节点之间相互独立
  • Memcached是C/S架构,C语言缩写的,全长2000行代码
  • Memcached是异步I/O结构,使用libevent作为事件通知机制
  • 被缓存的数据以KV键值对的形式存储
  • 全部数据都放入内存中,无持久性存储的设计。重启服务器所有数据丢失
  • 当内存中存储的数据容量达到启动时设定的内存值时,会自动使用LRU算法删除过期的缓存数据。
  • 可以对存储的数据设定过期时间,这样过期的数据会自动被清楚。服务器本身不会监控过期,而是访问的时候查看key的时间戳,判断是否过期。
  • memcached会在设定的内存中分块,再把块分组。然后再提供服务。(这一块的分块,分组是基于Memcached的内存管理机制,也就是Slab Allocation内存分配机制。不太懂的可以看下一道题)

4. 简述Memcached内存管理机制原理

早期的Memcached内存管理方式是通过malloc的分配的内存。使用完后通过free来回收内存。这种方式容易产生内存碎片。并降低操作系统对内存的管理效率。加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。为了解决 这个问题,Slab Allocation内存分配机制就诞生了。

现在Memcached利用Slab Allocation机制来分配和管理内存。

Slab Allocation

Slab Allocation机制原理是按照预先规定的大小,将分配给memcached的内存分割成特定长度的内存块。再把尺寸相同的内存块分成组。Slab Allocation有重复使用已分配的内存的目的。也就是说分配到的内存不会释放,而是重复利用。
Slab Allocation的主要术语:

  • Page:
    分配给Slab的内存空间默认是1MB,分配给Slab之后根据slab的大小切分成chunk。
  • Chunk
    用户缓存记录的内存空间(也可以理解成块)。
  • SlabClass
    特定大小的chunk的组。

5. Memcached是怎么工作的?

神奇的两阶段哈希(two-stage hash)
其实这个是个很有意思的设计。属于两次查询。我们之前说过了Memcached里存储的是KV对的hash表。通过key可以存储或查询任意的数据。
但是这里有个查询问题。在一百个数据中查询一个和在一万个数据中查询一个。肯定是一百个快啊。
所以Memcached的集群差不多如此效果:一万个数据分100个节点存储。一个节点存100个数组。
然後查询的时候先参考节点列表计算出key 的哈希值(阶段一哈希)。进而选中一个节点。
然後在memcached节点中通过一个内部的hash算法(阶段二哈希)查找真正的数据。

6. Memcached最大的优势是什么?

Memcached最大的好处就是它带来了极佳的水平扩展性。特别是在一个巨大的系统中。
由于客户端自己做了一个hash。我们很容易把心的memcached添加到集群中。
memcached之间没有相互通信,所以集群扩招也不会增加memcached的负载。没有多播协议也就不会网络通信量爆炸。
总而言之,这个memcached有点类似与mysql的分库(注意是分库而不是分表)。

7. memcached和MySQL的query cache相比,有什么优缺点?

我看的这本书上说Memcached引用复杂。但是现在2021年了,spring boot都到2了,其自带的Memcached已经配置好了。可以直接使用。注解版的话只需要添加几个注解就可以解决。所以不能说使用复杂了。
然后优点相比于MySQL的query cache有一下几点:

  1. 修改表的时候MySQL的query cache会立刻被刷新。当写操作很频繁的时候MySQL的query cache会经常让所有缓存数据失效。
  2. 多核CPU上,query cache会增加一个全局锁。所以当需要刷新的数据变多时,速度会变慢。
  3. MySQL的query cache只能存储SQL查询结果。而Memcached则可以存储任意的数据。
  4. query cache能利用的内存容量受到MySQL服务器的空闲内存空间的限制。而Memcached只要有空闲的内存都可以用来增加Memcached集群的规模。

简单总结下:Memcached存储不局限于sql语句,query cache只能存sql运行结果。query cache依赖MySQL服务器的空闲内存。Memcached不局限。Memcached更加灵活方便和便于使用。

8. Memcached的cache机制是怎么样的?

这个其实上文已经简单的提到了。主要的cache机制是LRU算法+超时失效。
存数据到Memcached的时候,可以指定该数据在缓存中待多久。然后当Memcached的内存不够用了优先把过期的slabs替换,如果过期都替换了还是不够用,就把最长时间未被使用的slabs替换。

9. Memcached如何实现冗余机制?

这个问题其实是个坑。因为Memcached根本不带任何冗余机制。Memcached应该是应用的缓存层。简单来说应该是一个有了更好,没有也可以的作用。如果就因为没有了Memcached就程序出问题了说明设计的有问题。。。
应该特别注意:我们的应用应该可以容忍任何节点的失效。也就是如果Memcached节点失去了所有的数据,也应该可以从数据源(比如数据库)再次获取到数据。
当然了如果担心节点失效会加大数据库的负担,可以选择别的方式:比如增加更多的节点。热备节点等。

10. Memcached如何处理容错的?

依然是坑。因为结果是不处理。在Memcached节点失效的情况下,集群没有必要做任何容错处理。如果发生了节点失效,应对的措施完全取决于用户。节点失效时,下面几种方案可以选择:

  1. 忽略他。down就down了。等修好了再说。反正只是一部分数据而已。数据库一点压力没问题的。
  2. 失效的节点从节点列表移除。 这个很严肃,因为默认情况下(余数式哈希算法)客户端添加或者删除节点会法制所有的缓存数据不可用。会从新分配所有的key的所在节点。
  3. 启动热备节点,就是当有down掉的接管失效节点所占用的ip。防止哈希紊乱。
  4. 两次hash。如果存数据发现第一个hash的节点down了,直接再做一次与第一次不同的hash,存储到另一个节点上。当然取的时候也先去第一个down的节点取,没有结果去第二个取。
    需要注意这种方式的话千万别节点时好时坏。。不然有脏数据的风险。

11. 如何将Memcached中kv对批量导入导出?

这是一个不应该的操作。Memcached的特性(缓存在内存。非阻塞。)如果在导入导出期间数据发生了变化,就会产生脏数据了。
当然了,有些东西比如几乎从不变化,但是因为经常使用所以存在内存(比如省市区,轻易不变化。)我们确实可以在一开始把这些信息导入进缓存。但是注意:
Memcached是可以减轻数据库压力。但是不是说我们有了缓存就高枕无忧了,改优化查询还是要优化查询的!我们应该让Memcached实现的是如虎添翼,雪上添花的功能。而不能说没有了Memcached就整个程序崩溃了。

12. Memcached是如何做身份验证的?

注意这个题又是一个坑!因为Memcached是没有身份认证机制的。Memcached是运行在应用下层的软件。身份验证应该是应用上层的职责
Memcached的客户端和服务端之所以是轻量级的,部分原因就是完全没有实现身份验证机制。这样可以很快的创建新连接。服务端也无需任何配置。

13. Memcached的多线程是什么?如何使用它们?

Memcached1.2及以上才有多线程模式。多线程允许Memcached能够充分利用多个cpu。并在CPU之间共享所有的缓存数据。Memcached使用一种简单的锁机制来保证数据更新操作的互斥。相比同一个物理机上运行多个Memcached实例。这种方式更能够有效的处理存取。
当然了,如果系统负载并不重的情况下,也许不需要启用多线程工作模式。
简单总结一下:命令解析可以运行在多线程的模式下。Memcached内部对数据的操作是基于很多全局锁的(因为这部分不是多线程)。未来对多线程的改进应该是移除大量全局锁,提高Memcached在负载极高的场景下的性能。

14. Memcached能接受的key的最大长度是多少?

key的最大长度是250个字符。需要注意的是250是memcached服务器端内部的限制。
如果您的客户端支持key的前缀或者类似特性,那么实际key=前缀+原始key。其实最大长度是可以超过250字符的。但是我们推荐使用短的key,因为较短的key可以节省内存和宽带。

15. Memcached对item的过期时间有什么限制?

过期时间最大可以达到30天。Memcached吧传入的过期时间解释成一个时间点(我们可以理解为时间戳)。一旦到了这个时间点,Memcached就把item设置为失效状态。

16. Memcached最大能存储多大的单个item?

1MB(为什么是1MB呢?内存分配器的算法就是这样的!),如果数据大于1MB,可以考虑在客户端压缩或者拆分到多个key中。

17. Memcached如何更有效的使用内存?

Memcached客户端仅仅根据哈希算法来决定将某个key存储在哪个节点上。而不考虑节点的内存大小。因为我们可以在不同的节点上使用大小不等的缓存。但是一般都是这么做的:在拥有较多内存的节点上可以运行多个Memcached示例。使得每个实例使用的内存跟其他节点上的实例相同(人为去控制)。

18. Memcached的内存分配器是如何工作的?为什么不适用malloc/free?为什么要使用slabs?

其实这个最开始的时候Memcached确实是使用malloc/free来管理内存的。然后在实际工作中发现这种方式不能很好的工作。因为反复的malloc/free会造成内存碎片。OS最终花费大量的时间去查找连续的内存块来满足malloc的请求而不是运行memcached的进行。
(这一块可以联想java的垃圾回收机制来理解-标记清除的过时原因。)

19. Memcached是原子的么?

所有被发送到Memcached的单个命令都是原子的。这个有点类似于redis。就是保证每一个命令的原子性。如果发送了一个命令组:先set,再get。他们不会影响多方。会被串行化,先后执行。
但是问题来了!!!如果你发送一个命令组:set/get。但是不敢保证你get到的是你set的数据。因为可能有别的线程在你set后有把这个值set成了新值。你get到的也就是新值了。(和redis一毛一样)
然後memcached1.2.5以上提供了一些解决命令序列的原子问题。有点类似CAS的版本号。就是每次修改都带个版本号。版本号不一致写会失败。

20. 如何实现集群中的session共享存储?

其实我觉得这个题有点跟Memcached没啥关系了。是设计架构上的 单点登录吧?
反正看到了就要记录一下。先说一下什么是单点登录:Session是运行在一台服务器上的。我们可以根据客户端传来的sessionId获取session。如果session不存在则说明用户没登陆或者登录过期了。这个时候需要重新登陆。
但是问题来了。如果是集群环境下有多台服务器,那么请求会由Nginx转发。用户登录时nginx把请求转发其中一台服务器上。这个服务器创建了session并返回给客户端sessionId。但是如果下次请求被负载到其余的服务器上,那么这个session是不存在的。所以要重新登录。这种情况多了用户体验就不好了。
解决办法其实也很多。简单说几个:

  1. 粘性session
    Nginx将同一个用户请求转发至同一台服务器。(这种我个人觉得不好,而且失去了集群的意义。如果一台服务器挂了呢?并且每次转发也要多处理)
  2. 服务器session复制
    每次session发生变化(增删改)广播给所有集群中的服务器。使得所有服务器上session一致
  3. session共享
    这个有点类似于第二种方式的进化版。想要共享每个客户端都存麻烦的很。直接把session提出来单独存,但是每个服务器都可以读取。这个用redis,memcached都可以。
  4. session持久化
    这个其实目的和2,3一直。都是为了数据共享。只不过实现方式不同。都放到数据库,每个服务器都可以去读。

21. memcached和redis的区别?

这个是memcached的最后一道问答题。其实二者相似点很多,当然了肯定区别也是有的,下面一点点慢慢说

  • redis不仅仅支持简单的k/v类型数据。还支持list。set,zset,hash等数据结构的存储。而memcached只支持简单的数据类型。需要客户端自己处理复杂对象
  • redis支持数据的持久化(aof(文件追加)或者rdb(快照))
  • 因为memcached不能持久化,所以down机所有数据丢失,redis则有一定的灾备机制。
  • Memcached可以使用Magent在客户端进行一致性hash做分布式。而redis只能在服务端做分布式
  • Memcached的限制就是简单的kv限制。比如key的最大长度250.时间最长30天。存储数据不能超过1MB(超过了要压缩或者自己分几个key存)这是典型的slab的最大值,不适合虚拟机使用。而redis的key最长可以支持到512k。
  • Redis使用的是单线程模式。保证了数据按顺序提交。Memcached是使用cas保证数据一致性。
  • cpu利用上:redis只是用单核。而Memcached可以使用多核。所以当数据小的时候一个核上的redis比多核的Memcached性能更高。但是在100k以上的数据中,Memcached性能要高于Redis。
  • Memcached的内存管理使用Slab Alloction。原理相当简单:预先分配一系列大小固定的组。然後根据数据大小选择最合适的块存储。避免了内存碎片。但是缺点是不能变长,会浪费一定的空间(我们可以想象饭店的包厢:4人房,8人房,12人房。20人房。进去一波客人根据自己的人数去选择房型。但是假如去了15个人也只能选20人房。这个房间就空了5个位置。算是浪费了。)Memcached默认情况下下一个slab的最大值为前一个的1.25倍。
    而Redis的内存管理:Redis通过定义一个数组来记录所有的内存分配情况。Redis采用的是包装的malloc/free。相较于Memcached的内存管理方法来说要更简单。犹豫malloc首先以链表的方式搜索以管理的内存中可用的空间分配,可能导致内存碎片较多。(还是按照饭店来想象:这个没有包厢,就是一个大圆桌。贼大的圆桌。一起去吃饭的人去挨着坐就行了。但是问题来了。客人来来走走,如果出了偶尔有两个空位,偶尔有三个空位,偶尔有一个空位的情况,这个时候如果来了一波10个人。明明空位置还有,但是因为不挨着。所以这是五个人就不吃了!这个就是内存碎片多但是又无法合理的复用!)

大概Redis和Memcached的区别就这么些吧,主要是内存管理,持久化,cpu利用,存储的数据结构几个方面。

本篇笔记就记到这里,如果稍微帮到你了记得点个喜欢点个关注。也祝大家工作顺顺利利吧!愿所有的付出都有回报,愿所有的汗水都不白流!ps:最近正在求职,所以一直啃面试题。欢迎同样的小伙伴们加个好友互通有无哟!

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

推荐阅读更多精彩内容