zoukankan      html  css  js  c++  java
  • Memcached快速入门


    1.基本概念
    基于高性能的key-value的内存数据库。单进程多线程,协议简单,使用文本行的协议,支持数据类型简单,不支持持久化,轻量级锁CAS机制,集群互不通信,缓存策略(LRU,FIFO,LFU)只支持LRU
    2.与redis对比
    redis: 线程模型-单进程单线程,QPS/TPS-10w+/10w-,数据支持类型-丰富,持久化-支持, 支持数据备份-支持, 能否集群-能,数据一致性-支持事务, list排序支持-支持, 缓存策略-LRU,FIFO,LFU,jcache支持-支持,单条数据约束-不同数据结构有不同约束
    memcached: 线程模型-单进程多线程,QPS/TPS-10w+/10w-,数据支持类型-简单,持久化-不支持,支持数据备份-不支持,能否集群-能,数据一致性-轻量级CAS机制,list排序支持-不支持,缓存策略-LRU, jcache支持-支持,单条数据约束-默认值:key最大长度250字符,value容量<=1M
    3.安装及使用
    参考:http://www.runoob.com/memcached/memcached-install.html

    wget http://memcached.org/latest
    tar -zxvf memcached-1.x.x.tar.gz
    cd memcached-1.x.x
    ./configure && make && make test && sudo make install

    启动:./memcached -p 11211 -d -c 1024 -u root (-p 表示端口,-d 表示后台运行, -u 指定用户)
    停止:ps aux|grep memcached 查到进程id,然后 kill -9 pid

    客户端:没有专门的客户端,使用telnet ip port

    集群:在同一台机器上可以通过指定不同的端口来运行,如
    ./memcached -p 11211 -d -c 1024 -u root
    ./memcached -p 11212 -d -c 1024 -u root
    ./memcached -p 11213 -d -c 1024 -u root

    4.memcached客户端使用
    1.memcached-java-client
    引入pom:
    <!-- memcached-java-client -->
    <!-- https://mvnrepository.com/artifact/com.whalin/Memcached-Java-Client -->
    <dependency>
    <groupId>com.whalin</groupId>
    <artifactId>Memcached-Java-Client</artifactId>
    <version>3.0.2</version>
    </dependency>

    详见:MemcachedJavaClientTest

    2.spymemcached
    引入pom:
    <!--spymemcached-->
    <!-- https://mvnrepository.com/artifact/net.spy/spymemcached -->
    <dependency>
    <groupId>net.spy</groupId>
    <artifactId>spymemcached</artifactId>
    <version>2.12.3</version>
    </dependency>

    详见:MemcachedJavaClientTest

    3.xmemcached
    引入pom:
    <!-- xmemcached -->
    <!-- https://mvnrepository.com/artifact/com.googlecode.xmemcached/xmemcached -->
    <dependency>
    <groupId>com.googlecode.xmemcached</groupId>
    <artifactId>xmemcached</artifactId>
    <version>2.4.5</version>
    </dependency>
    详见:MemcachedJavaClientTest

    4.springcache与xmemcached 整合
    引入pom:
    <!-- xmemcached -->
    <!-- https://mvnrepository.com/artifact/com.googlecode.xmemcached/xmemcached -->
    <dependency>
    <groupId>com.googlecode.xmemcached</groupId>
    <artifactId>xmemcached</artifactId>
    <version>2.4.5</version>
    </dependency>
    <!-- spring cache 与 xmemcached 整合 采用simple-spring-memcached实现 -->
    <dependency>
    <groupId>com.google.code.simple-spring-memcached</groupId>
    <artifactId>simple-spring-memcached</artifactId>
    <version>2.0.0</version>
    </dependency>
    配置:applicationContext-cache.xml

    详见:SpringCacheMemcachedTest
    5.原理(重点理解)

    5.1.hash算法
    memcached单节点是有存储局限的,所以可以使用集群的方式。这里就有分布式存取的问题。不管是写入还是读取,肯定要通过某种算法,这种算法负责定位到某个固定的节点

    1.余数分散:m = hash(key) mod n (其中key为传入的数据,n为机器的个数 ,将计算得到的m值 就是对应第几台机器,将key存入改机器中)
    优点:算法简单,分散性好
    缺点:当新增或者删除机器时,缓存重组的代价很大。当新增或删除机器时,余数会有很大的变化,这样就无法获取与保存时同样的机器,从而导致缓存的命中率很低
    代码详见:HashTest

    2.一致性hash算法
    一致性hash算法就是为了解决余数分散 增加或删除机器时命中率低的问题
    步骤:1.构建hash环 2.把数据映射到hash环 3.把机器节点映射到hash环 4.把数据映射到机器节点
    优点:解决了余数分散算法增加或删除节点命中率大幅下降的问题
    缺点:算法实现比较复杂,需要构建hash环
    代码详见:ConsistentHashTest ConsistentHashNodeServiceImpl

    3.一致性hash算法 + 虚拟节点
    一致性hash算法有个缺点:数据分布不均,有倾斜性,即有些节点存的数据很多,有些则很少。
    为了解决这个问题,于是有了增加虚拟节点的方案:
    可以在原来缓存的机器的基础上,增加相应的虚拟节点,这样数据就会均匀的打散到其他节点中。这个时候客户端进行数据存取的时候找的就是虚拟节点,而不是真实的物理节点服务器,这样增加节点会删除节点虽然命中率会降低,却很好的解决了数据倾斜问题
    代码详见:ConsistentHashTest ConsistentHashNodeServiceImpl2

    5.2内存管理策略
    Memcached采用Slab Allocator(Slab分配器)进行内存管理
    内存被拆分成多个Slab class
    每个Slab class 有多个Slab,每个Slab=1M
    每个Slab下有多个大小相等的Chunk
    不同Slab中的Chunk的大小不一样
    数据存储在Chunk中

    使用./memcached -p 11211 -d -u root -vv 可以观察内存分配情况
    客户端Telnet使用stats slabs查看内存分布情况

    增长因子:
    启动时指定增长(growth factor)因子(-f 2),就可以在某种程度上控制slab之间的差异,默认值为1.25
    如果增加-f 2参数即 ./memcached -p 11211 -f 2 -d -u root -vv 那么表示每一个slab的chunk size 都比上一个slab大了一倍

    注意:真实项目中,要均衡数据的大小,如果数据之间大小差别不大建议增长因子设置比较小,而数据之间大小悬殊,数据的增长因子可以考虑增大

    5.3缓存过期策略
    MC不会主动删除过期数据,而是采用lazy策略
    Memcached不会释放已分配的内存,其存储空间可以重复使用
    Memcached内部不会监视数据是否过期,而是在get时查看数据的时间戳,查看数据是否过期。被称为lazy expiration(惰性过期)
    Memcached内存空间不足,即无法从slab class中获取到新的空间时,就从最近未被使用的数据中搜索,将其空间分配给新的数据。(如果要禁用LRU,使用-M参数,超出会报错)


    6.问题

    1.什么是一致性hash,他和普通hash有什么不同(hash环,虚拟节点干什么的)?
    一致性hash是为了解决普通hash算法(余数分散算法)因增加或删除节点导致命中率大幅下降的问题 而产生的
    与普通hash不同点:
    1.构建hash环 2.将数据映射到hash环上 3.将节点映射到hash环上 4.将数据映射到节点上
    虚拟节点:是为了解决一致性hash中节点个数少导致数据分布不均问题而产生的,通过增加虚拟节点,可以使得数据均匀的打散到其他节点。
    2.一致性hash在上面情况下使用,单节点情况下用一致性hash是否合适?
    单节点不适用,因为使用一致性hash算法性能比较低,单节点使用普通的hash算法就行了
    3.slab内存模型是什么样的,对于增长因子来说,他对性能有什么影响?
    slab内存模型:
    内存被拆分成多个slab class
    每个slab class 有多个slab,每个slab=1M
    每个slab下有多个大小相等的chunk
    不同slab中chunk大小不一样
    数据存储在chunk中

    增长因子:
    用于控制slab之间的差异。默认是1.25,可以根据实际情况,设置增长因子(在启动memcached时加参数 -f 设置)
    如果数据之间的大小差别不大,就设置小点,如果大小差别很大,就可以设置大点

    4.增长因子对性能影响:
    如果数据间隔小,而设置很大的话,就浪费空间。
    如果数据间隔大,而设置很小的话,那就存不了数据,也是浪费空间
    如果增长因子设置过大,代表的每个slab里面chunk大小跨度很大。 但数据却很小,经常导致只有一部分chunk被使用 而且经常导致内存的清理,导致性能降低,如果数据跨度不大,可以考虑把增长因子设置得小一点的

    5.一致性hash环的大小为什么是2^32
    因为,java中int的最大值是2^31-1最小值是-2^31,2^32刚好是无符号整形的最大值;
    为什么java中int的最大值是2^31-1最小值是-2^31
    int的最大值最小值范围设定是因为一个int占4个字节,一个字节占8位,二进制中刚好是32位
    hash环:
    把二的三十二次方想象成一个圆,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、5、6……直到2^32-1,也就是说0点左侧的第一个点代表2^32-1,我们把这个由2的32次方个点组成的圆环称为hash环

    6.如果服务器计算出的hash值相同,那么数据不是被放在相同的服务器上了吗?
    这个问题其实就是hash 碰撞,而在一致性hash里面hash碰撞的几率不大,理论上有hash碰撞的可能性,任何hash的有可能。
    就像md5值,如果数据量足够大,足够长,算出的md5理论上可能重复,但并不影响它使用。 这是种出现概率极低的情况
    7.每个slab大小是1M,为什么slab class有39个?
    slab class有39个 只是显示它会这么分配,这个是由增长因子确定,但并没真的这么分配。具体的分配你应该在服务器运行的时候基于指定的内存分配,可以stats slabs命令查看

    8.一致性hash算法应用场景:
    memcached的客户端,redis中的hash slot(hash槽),nginx的负载均衡
    hash一致性算法是为了在分布式环境下 动态增加或删除节点 而尽量减少对数据存取的影响即命中率低的问题 而产生,具体的算法在不同的应用场景中不太一样

    9.缓存过期策略
    FIFO(First In First Out):先见先出,淘汰最先近来的页面,新进来的页面最迟被淘汰,完全符合队列
    LRU(least recently used):最近最少使用,淘汰最近不使用的页面
    LFU(least frequently used):使用次数最少, 淘汰使用次数最少的页面
    memcached 采用的是LRU
  • 相关阅读:
    vue-music 关于搜索历史本地存储
    Node.js中package.json中^和~的区别
    主流浏览器内核
    pm2 日常使用
    前端验证用户登陆状态(vue.js)
    ng-repeat循环出来的部分调用同一个函数并且实现每个模块之间不能相互干扰
    行内元素垂直方向位置调整的一些感悟和困惑
    由overflow-x:scroll产生的收获
    子代选择器(>)后代选择器(' ')的区别
    content相关属性
  • 原文地址:https://www.cnblogs.com/lookupthesky/p/10305186.html
Copyright © 2011-2022 走看看