memcache面试题

简介

Memcached 是一个开源的分布式缓存系统

提供键值类型的数据存储

 

 

特点:

提供内存存储,不提供磁盘存储

只支持单一的整体查询,不支持部分字段查询

不支持模糊查询,条件查找,也没有各种聚合函数对数据进行聚合查询

数据不能备份

memcache缓存最长有效期为30天,如果设置时间超过30天数据会添加不进去

memcache的单个命令是完全原子的。

memcache是多线程处理客户端请求(redis是单线程)

利用hash表实现存储

 

说明:

set命令指定失效时间为0代表永久存储。但空间不够时根据LRU算法可能会被删除

 

memcache最大的优势

Memcached 最大的好处就是它带来了极佳的水平可扩展性

memcached 之间没有相互通信,因此不会增加 memcached 的负载;

 

redis和memcache对比:

redis和memcache的单个命令都是原子的

redis单线程,memcache是多线程接收用户请求

redis支持多种数据类型,memcache只支持value的整个存储

reids支持持久哈,memcache不支持持久化

Memcache 可以使用 Magent 在客户端进行一致性 hash 做分布式。Redis 支

持在服务器端做分布式

 

memcache身份认证

没有身份认证机制!memcached 是运行在应用下层的软件(身份验证应该是应用

上层的职责)。

 

memcache多线程

命令解析(memcached 在这里花了大部分时间)可以运行在多

线程模式下。memcached 内部对数据的操作是基于很多全局锁的(因此这部分工

作不是多线程的)。

 

Memcache高性能原因

1.两阶段哈希结构:

  • 第一阶段在客户端,通过 Hash算法根据Key值算出一个节点;
  • 第二阶段在服务端,通过一个内部的Hash算法,查找真正的item并返回给客户端。从实现的角度看,MemCache是一个非阻塞的、基于事件的服务器程序
  1. 读写都是对内存操作

3、使用多路复用I/O模型,还使用多线程可以同时处理多个请求。

(redis也使用了多路复用io模型,不过是单线程处理客户端请求)

 

memcache查询过程

在一个memcached的查询中,Client先通过计算key的hash值来确定kv对所处在的Server位置。当Server确定后,客户端就会发送一个查询请求给对应的Server,让它来查找确切的数据。

memcache写缓存过程

1、应用程序输入需要写缓存的数据

 

2、API将Key输入路由算法模块,路由算法根据Key和MemCache集群服务器列表得到一台服务器编号

 

3、由服务器编号得到MemCache及其的ip地址和端口号

 

  • API调用通信模块和指定编号的服务器通信,将数据写入该服务器,完成一次分布式缓存的写操作

 

memcache如何处理容错

  • 启动热备节点,接管失效节点所占用的 IP。这样可以防止哈希紊乱
  • 一致性hash减少哈希紊乱

 

memcache主从

 

Memcache集群

memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能,各个memcached不会互相通信以共享数据,这完全取决memcached api的客户端所使用的路由算法;

通过客户端的算法把数据保存在不同的memcached中

 

Memcached常见分布式算法

1.余数Hash

 

将传入的key转换为Hash值

获取服务器数量列表

取余:Hash值%服务器数量

通过余数来选择具体存放/查询的服务器

优缺点:简便易理解、增加/减少节点会造成灾难

 

2.一致性Hash

 

将服务器列表+虚拟节点分布在0-2的32次方的一个圆上

将传入的key转换为Hash值

获取服务器数量列表

取余:Hash值%服务器数量

通过余数来选择具体存放/查询的服务器

如果余数命中虚拟节点,则会顺时针寻找真实Memcached服务

主流的是使用一致性hash算法来路由到memcache服务器

一致性hash的实现

java中使用treeMap

Memcache原理

Memcached 进程运行之后,会预申请一块较大的内存空间,自己进行管理,用完之后再申请一块,而不是每次需要的时候去向操作系统申请。Memcached将对象保存在一个巨大的Hash表中(这个hash表是还是用数组+链表的方式来实现的,数据量达到一定值也会进行扩容,迁移数据)

 

memcache过期机制

 

Memcache删除机制

空间不足的时候,Memcached会优先使用已经过期的数据空间,如果还不够,那么就会把最近最少使用的对象的空间释放出来使用。当某个单元被请求时,维护一个计数器,通过计数器来判断最近谁最少使用,就把谁踢出去。所以也有可能删除一些尚未过期或者永久有效的数据。

MemCache的LRU算法不是针对全局的,是针对slab的

 

懒惰删除机制

1.4.25及以前版本使用 惰性删除机制,不会自动清理,作删除标记,下次分配的时候直接使用

之后版本会隔指定时间进行查找是否有过期item,如果有过期会进行删除处理。

 

memcache的LRU:

LRU策略不是针对所有的slabs,而是只针对新数据应该被放入的slab,当数据应该放的chunk所在的slabs内存不够的时候就会使用LRU

LRU原理是根据访问时间把key放入一张链表,不断更新,这样队尾就是最长时间没有使用的。

memcache的LRU可以禁止,启动时添加-M参数就行,内存用尽时memcached会返回错误

 

memcache连接限制

最大连接数限制为1024

Memcache内存使用原理

MemCache内存分配的方式称为allocator

 

Memcache的存储涉及到slab_class,slab,page,chunk四个概念

1、MemCache将内存空间分为一组slab

2、每个slab下又有若干个page,每个page默认是1M,如果一个slab占用100M内存的话,那么这个slab下应该有100个page

 

3、每个page里面包含一组chunk,chunk是真正存放数据的地方,同一个slab里面的chunk的大小是固定的,chunk的最小尺寸可以通过memcache的启动参数指定,page固定为1m,所以chunk最大不能超过1m。

4、有相同大小chunk的slab被组织在一起,称为slab_class

 

MemCache中的value过来存放的地方是由value的大小决定 的,value总是会被存放到与chunk大小最接近的一个slab中,比如slab[1]的chunk大小为80字节、slab[2]的chunk大小 为100字节、slab[3]的chunk大小为128字节(相邻slab内的chunk基本以1.25为比例进行增长,MemCache启动时可以用-f指定这个比例), 那么过来一个88字节的value,这个value将被放到2号slab中。放slab的时候,首先slab要申请内存,申请内存是以page为单位的, 所以在放入第一个数据的时候,无论大小为多少,都会有1M大小的page被分配给该slab。申请到page后,slab会将这个page的内存按 chunk的大小进行切分,这样就变成了一个chunk数组,最后从这个chunk数组中选择一个用于存储数据。

 

如果这个slab中没有chunk可以分配了怎么办,如果MemCache启动没有追加-M(禁止LRU,这种情况下内存不够会报Out Of Memory错误),那么MemCache会把这个slab中最近最少使用的chunk中的数据清理掉,然后放上最新的数据。

 

总结:

memcache存储数据的最小单位是chunk,大小相等的chunk组成了page,page默认大小是1M,多个page组成了slab;相同大小chunk的slab被组织在一起,称为slab_class

同一个slab中的chunk大小都是一样的,value过来后会被存放到与chunk大小最接近的一个slab中

内存删除策略是针对slab的

为什么这样使用

避免浪费内存

memcached键值大小限制

Memcached是键值一一对应,key默认最大不能超过250个字节,value默认大小是1M

在memcached.h中定义key的长度,超过该长度无法存储

Redis 的 Key 长度支持到 512k。

 

为什么限制key的长度

主要是节省内存,节省带宽,而且可以存储到更加高效的slab class

key为什么限制250字节

 

限制key的长度

  • 可以使用缩写来减少长度
  • 使用base64编码来缩短key
  • 使用二进制协议序列化

数据大于1M的问题

如果数据大小大于1M,数据会添加失败

Memcahce默认的page大小为1M,可以启动的时候指定大小,由于数据是存放在page中的chunk中的,所以chunk的大小最大就是page的大小,所以数据默认最大限制为1M

真的要存大于1M的怎么办

可以考虑在客户端压缩或拆分到多个key中。

 

memcache高可用

由于memcache本身服务器之间无法进行通信所以无法做主从,可以通过magent软件来实现

magent是一款开源的代理服务软件,我们可以通过他来实现缓存数据的同步,当然这里说的同步不是说memcached之间就能互相通讯了,而是magent可以备份数据,而magent可以同时连接多个memcached节点,当memcached重启或者宕机恢复后可以从magent指定的memcached的备份节点中恢复丢失的缓存数据。

 

memcache扩容

只需要添加额外的服务并修改客户端配置。

memcache缓存30天

memcached的过期时间,有一个最大时限就是30天,设置时若超过30天,存储时返回true,但是在获取数据的时候取不到

 

memcache常用命令

运行参数

-p 监听的端口

-l 连接的IP地址, 默认是本机  

-d start 启动memcached服务

-d restart 重起memcached服务

-d stop|shutdown 关闭正在运行的memcached服务

-d install 安装memcached服务

-d uninstall 卸载memcached服务

-u 以的身份运行 (仅在以root运行的时候有效)

-m 最大内存使用,单位MB。默认64MB

-M 内存耗尽时返回错误,而不是删除项

-c 最大同时连接数,默认是1024

-f 块大小增长因子,默认是1.25

-n 最小分配空间,key+value+flags默认是48

-h 显示帮助

 

如:

Memcached.exe –d  -m 50 –l 127.0.0.1  -p 11211 start

其他命令

Command

Description

Example

get

返回Key对应的Value值

get mykey

set

无条件地设置一个Key值,没有就增加,有就覆盖,操作成功提示STORED

set mykey 0 60 5

add

Add a new key

add newkey 0 60 5

replace

按照相应的Key值替换数据,如果Key值不存在则会操作失败

replace key 0 60 5

append

Append data to existing key

append key 0 60 15

prepend

Prepend data to existing key

prepend key 0 60 15

incr

Increments numerical key value by given number

incr mykey 2

decr

Decrements numerical key value by given number

decr mykey 5

delete

Deletes an existing key

delete mykey

flush_all

清空所有键值,但不会删除items,所以此时MemCache依旧占用内存

flush_all

Invalidate all items in n seconds

flush_all 900

stats

返回MemCache通用统计信息

stats

返回MemCache运行期间创建的每个slab的信息

stats slabs

Prints memory statistics

stats malloc

返回各个slab中item的数目和最老的item的年龄(最后一次访问距离现在的秒数)

stats items

 

stats detail

 

stats sizes

Resets statistics

stats reset

version

返回当前MemCache版本号

version

verbosity

Increases log level

verbosity

quit

关闭连接

quit

 

stats命令

stats

STAT pid 1162

STAT uptime 5022

STAT time 1415208270

STAT version 1.4.14

STAT libevent 2.0.19-stable

STAT pointer_size 64

STAT rusage_user 0.096006

STAT rusage_system 0.152009

STAT curr_connections 5

STAT total_connections 6

STAT connection_structures 6

STAT reserved_fds 20

STAT cmd_get 6

STAT cmd_set 4

STAT cmd_flush 0

STAT cmd_touch 0

STAT get_hits 4

STAT get_misses 2

STAT delete_misses 1

STAT delete_hits 1

STAT incr_misses 2

STAT incr_hits 1

STAT decr_misses 0

STAT decr_hits 1

STAT cas_misses 0

STAT cas_hits 0

STAT cas_badval 0

STAT touch_hits 0

STAT touch_misses 0

STAT auth_cmds 0

STAT auth_errors 0

STAT bytes_read 262

STAT bytes_written 313

STAT limit_maxbytes 67108864

STAT accepting_conns 1

STAT listen_disabled_num 0

STAT threads 4

STAT conn_yields 0

STAT hash_power_level 16

STAT hash_bytes 524288

STAT hash_is_expanding 0

STAT expired_unfetched 1

STAT evicted_unfetched 0

STAT bytes 142

STAT curr_items 2

STAT total_items 6

STAT evictions 0

STAT reclaimed 1

END

 

这里显示了很多状态信息,下边详细解释每个状态项:

 

pid: memcache服务器进程ID

uptime:服务器已运行秒数

time:服务器当前Unix时间戳

version:memcache版本

pointer_size:操作系统指针大小

rusage_user:进程累计用户时间

rusage_system:进程累计系统时间

curr_connections:当前连接数量

total_connections:Memcached运行以来连接总数

connection_structures:Memcached分配的连接结构数量

cmd_get:get命令请求次数

cmd_set:set命令请求次数

cmd_flush:flush命令请求次数

get_hits:get命令命中次数

get_misses:get命令未命中次数

delete_misses:delete命令未命中次数

delete_hits:delete命令命中次数

incr_misses:incr命令未命中次数

incr_hits:incr命令命中次数

decr_misses:decr命令未命中次数

decr_hits:decr命令命中次数

cas_misses:cas命令未命中次数

cas_hits:cas命令命中次数

cas_badval:使用擦拭次数

auth_cmds:认证命令处理的次数

auth_errors:认证失败数目

bytes_read:读取总字节数

bytes_written:发送总字节数

limit_maxbytes:分配的内存总大小(字节)

accepting_conns:服务器是否达到过最大连接(0/1)

listen_disabled_num:失效的监听数

threads:当前线程数

conn_yields:连接操作主动放弃数目

bytes:当前存储占用的字节数

curr_items:当前存储的数据总数

total_items:启动以来存储的数据总数

evictions:LRU释放的对象数目

reclaimed:已过期的数据条目来存储新数据的数目

 

 

memcache的操作是原子的吗

memcached的单个命令是完全原子的

memcache的incr操作也是原子操作,如果对应的key不存在,会报错

memcache配置

服务器端配置

memcache启动命令指定配置内容,没有配置文件

如:memcached -m 512 -u root -d -l 127.0.0.1 -p 11211

 

-d  # 以后台守护进程的方式运行,等于--daemon参数,默认是关闭了的

-u  # 指定以哪个用户来运行,等于--user参数,默认是root用户

-l  # 指定监听的IP地址,等于--listen参数,默认监听的是0.0.0.0 即所有IP地址

-p  # 指定监听的端口,等于--port参数,默认监听的是11211,具体用啥看你的规划

-t  # 指定线程数,等于--threads参数,默认是两个;

-P  #(大写P) 生成pid文件,并指定pid文件保存的位置,等于--pidfile参数,默认是不会生成的;

-s  # 生成socket文件,并指定socket文件保存的午饭了,等于--socket参数,默认是不会生成的;

-c  # 指定最大并发连接数,等于--conn-limit参数,默认是1024;

-------------------------------------------------------------------------------------------------------------------

-m  # 指定分配多少内存,单位是M,等于--memory-limit参数,默认值是64,那就是64M

应用端配置

服务器ip及端口列表

servers host1:11211,host2:11211,host3:11211

 

memcache做集群

1程序端进行使用路由算法路由服务器

2使用负载均衡器

为什么这样做集群

这种MemCache集群的方式也是从分区容错性的方面考虑的,假如Node2宕机了,那么Node2上面存储的数据都不可用了,此时由于集群中Node0和Node1还存在,下一次请求Node2中存储的Key值的时候,肯定是没有命中的,这时先从数据库中拿到要缓存的数据,然后路由算法模块根据Key值在Node0和Node1中选取一个节点,把对应的数据放进去,这样下一次就又可以走缓存了,这种集群的做法很好,但是缺点是成本比较大。

Magent

Magent是一款开源的Memcached代理服务器软件,使用它可以搭建高可用性的集群应用的Memcached服务

采用一致性hash路由算法

 

Libevent和memcache

 

其他

MemCachedMemCache

MemCache是项目的名称

MemCached是MemCache服务器端可以执行文件的名称

 

posted @ 2023-02-02 09:19  星光闪闪  阅读(119)  评论(0)    收藏  举报