zoukankan      html  css  js  c++  java
  • Memcached缓存

    1. 简介

    Memcached只支持能序列化的数据类型,不支持持久化,基于Key-Value的内存缓存系统。

    1.2 内存分配机制

    应用程序运行需要使用内存存储数据,但对于一个缓存系统来说,申请内存、释放内存将十分频繁,非
    常容易导致大量内存碎片,最后导致无连续内存空间可用。
    Memcached采用了Slab Allocator机制来分配、管理内存

    • Page:分配给Slab的内存空间,默认为1MB,分配后就得到一个Slab。Slab分配之后内存按照固
      定字节大小等分成chunk。
    • Chunk:用于缓存记录kv值的内存空间。Memcached会根据数据大小选择存到哪一个chunk中,
      假设chunk有128bytes、64bytes,数据只有100bytes存储在128bytes中,存在些浪费。
      • Chunk最大就是Page的大小,即一个Page中就一个Chunk
    • Slab Class:Slab按照大小分组,就组成不同的Slab Class

    如果有100bytes要存,那么Memcached会选择上图中Slab Class 2存储,因为它是120bytes的
    Chunk。

    Slab之间的差异可以使用Growth Factor控制,默认1.25。

    1.3 懒过期Lazy Expiration

    memcached不会监视数据是否过期,而是在取数据时才看是否过期,过期的把数据有效期限标识为0,
    并不清除该数据。以后可以覆盖该位置存储其它数据。

    1.4 LRU

    当内存不足时,memcached会使用LRU(Least Recently Used)机制来查找可用空间,分配给新纪录
    使用。

    1.5 集群

    Memcached集群,称为基于客户端的分布式集群。
    Memcached集群内部并不互相通信,一切都需要客户端连接到Memcached服务器后自行组织这些节
    点,并决定数据存储的节点。

    2. 安装

    # yum install memcached
    # rpm -ql memcached
    /etc/sysconfig/memcached
    /usr/bin/memcached
    /usr/bin/memcached-tool
    /usr/lib/systemd/system/memcached.service
    /usr/share/doc/memcached-1.4.15
    /usr/share/doc/memcached-1.4.15/AUTHORS
    /usr/share/doc/memcached-1.4.15/CONTRIBUTORS
    /usr/share/doc/memcached-1.4.15/COPYING
    /usr/share/doc/memcached-1.4.15/ChangeLog
    /usr/share/doc/memcached-1.4.15/NEWS
    /usr/share/doc/memcached-1.4.15/README.md
    /usr/share/doc/memcached-1.4.15/protocol.txt
    /usr/share/doc/memcached-1.4.15/readme.txt
    /usr/share/doc/memcached-1.4.15/threads.txt
    /usr/share/man/man1/memcached-tool.1.gz
    /usr/share/man/man1/memcached.1.gz
    # cat /usr/lib/systemd/system/memcached.service
    [Service]
    Type=simple
    EnvironmentFile=-/etc/sysconfig/memcached
    ExecStart=/usr/bin/memcached -u $USER -p $PORT -m $CACHESIZE -c $MAXCONN $OPTIONS
    # cat /etc/sysconfig/memcached
    PORT="11211"
    USER="memcached"
    MAXCONN="1024"
    CACHESIZE="64"
    OPTIONS=""
    前台显示看看效果
    # memcached -u memcached -p 11211 -f 1.25 -vv
    # systemctl start memcached 	
    

    修改memcached运行参数,可以使用下面的选项修改/etc/sysconfifig/memcached文件

    • -u username memcached运行的用户身份,必须普通用户
    • -p 绑定的端口,默认11211
    • -m num 最大内存,单位MB,默认64MB
    • -c num 最大连接数,缺省1024
    • -d 守护进程方式运行
    • -f 增长因子Growth Factor,默认1.25
    • -v 详细信息,-vv能看到详细信息
    • -M 内存耗尽,不许LRU
    • -U 设置UDP监听端口,0表示禁用UDP

    协议

    查看/usr/share/doc/memcached-1.4.15/protocol.txt

    
    # yum install telnet
    # telnet localhost 11211
    stats
    add mykey 1 60 4
    test
    STORED
    get mykey
    VALUE mykey 1 4
    test
    END
    set mykey 1 60 5
    test1
    STORED
    get mykey
    VALUE mykey 1 5
    test1
    END
    

    3. session共享服务器

    3.1 msm

    msm(memcached session manager)提供将Tomcat的session保持到memcached或redis的程序,
    可以实现高可用。
    目前项目托管在Github,https://github.com/magro/memcached-session-manager
    支持Tomcat的6.x、7.x、8.x、9.x。

    Tomcat的Session管理类,Tomcat版本不同

    • memcached-session-manager-2.3.2.jar
    • memcached-session-manager-tc8-2.3.2.jar

    Session数据的序列化、反序列化类

    • 官方推荐kyro
    • 在webapp中WEB-INF/lib/下

    驱动类

    • memcached(spymemcached.jar)
      Redis(jedis.jar)

    3.2 安装

    https://github.com/magro/memcached-session-manager/wiki/SetupAndConfifiguration
    将spymemcached.jar、memcached-session-manage、kyro相关的jar文件都放到Tomcat的lib目录中
    去,这个目录是 $CATALINA_HOME/lib/ ,对应本次安装就是/usr/local/tomcat/lib。

    
    asm-5.2.jar
    kryo-3.0.3.jar
    kryo-serializers-0.45.jar
    memcached-session-manager-2.3.2.jar
    memcached-session-manager-tc8-2.3.2.jar
    minlog-1.3.1.jar
    msm-kryo-serializer-2.3.2.jar
    objenesis-2.6.jar
    reflectasm-1.11.9.jar
    spymemcached-2.12.3.jar
    

    3.3 sticky模式

    • 原理
      当请求结束时Tomcat的session会送给memcached备份。即Tomcat session为主session,
      memcached session为备session,使用memcached相当于备份了一份Session。
      查询Session时Tomcat会优先使用自己内存的Session,Tomcat通过jvmRoute发现不是自己的
      Session,便从memcached中找到该Session,更新本机Session,请求完成后更新memcached。

    • 部署

    
    <t1> <t2>
    .  / .
    . X .
    . /  .
    <m1> <m2>
    

    t1和m1部署在一台主机上,t2和m2部署在同一台。

    • 配置

    放到 $CATALINA_HOME/conf/context.xml 中
    特别注意,t1配置中为failoverNodes="n1", t2配置为failoverNodes="n2"

    
    以下是sticky的配置
    <Context>
    ...
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:192.168.142.152:11211,n2:192.168.142.153:11211"
    failoverNodes="n1"
    requestUriIgnorePattern=".*.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
    </Context>
    

    memcachedNodes="n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211"

    memcached的节点们;n1、n2只是别名,可以重新命名。
    failoverNodes故障转移节点,n1是备用节点,n2是主存储节点。另一台Tomcat将n1改为n2,其主节
    点是n1,备用节点是n2。

    • 实验

    如果配置成功,可以在logs/catalina.out中看到下面的内容

    信息 [t1.magedu.com-startStop-1]
    de.javakaffee.web.msm.MemcachedSessionService.startInternal --------
    - finished initialization:
    - sticky: true
    - operation timeout: 1000
    - node ids: [n2]
    - failover node ids: [n1]
    - storage key prefix: null
    - locking mode: null (expiration: 5s)
    

    配置成功后,网页访问以下,页面中看到了Session。然后运行下面的Python程序,就可以看到是否存
    储到了memcached中了。

    
    import memcache # pip install python-memcached
    mc = memcache.Client(['192.168.142.152:11211', '192.168.142.153:11211'], debug=True)
    stats = mc.get_stats()[0]
    print(stats)
    for k,v in stats[1].items():
    print(k, v)
    print('-' * 30)
    # 查看全部key
    print(mc.get_stats('items')) # stats items 返回 items:5:number 1
    print('-' * 30)
    for x in mc.get_stats('cachedump 5 0'):# stats cachedump 5 0 # 5和上面的items返回的值有
    关;0表示全部
    print(x)
    
    

    t1、t2、n1、n2依次启动成功,分别使用http://t1.magedu.com:8080/ 和http://t2.magedu.com:808
    0/ 观察。
    看起负载均衡调度器,通过http://t0.magedu.com来访问看看效果

    On tomcats
    192.168.142.153:8080
    SessionID = 2A19B1EB6D9649C9FED3E7277FDFD470-n2.Tomcat1
    Wed Jun 26 16:32:11 CST 2019
    On tomcats
    192.168.142.152:8080
    SessionID = 2A19B1EB6D9649C9FED3E7277FDFD470-n1.Tomcat2
    Wed Jun 26 16:32:36 CST 2019
    

    可以看到浏览器端被调度到不同Tomcat上,但是都获得了同样的SessionID。
    停止t2、n2看看效果,恢复看看效果。

    3.4 non-sticky模式

    • 原理
      从msm 1.4.0之后开始支持non-sticky模式。
      Tomcat session为中转Session,如果n1为主session,n2为备session。产生的新的Session会发送给
      主、备memcached,并清除本地Session。
      n1下线,n2转正。n1再次上线,n2依然是主Session存储节点。

    • memcached配置
      放到 $CATALINA_HOME/conf/context.xml 中

    <Context>
    ...
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:192.168.142.152:11211,n2:192.168.142.153:11211"
    sticky="false"
    sessionBackupAsync="false"
    lockingMode="uriPattern:/path1|/path2"
    requestUriIgnorePattern=".*.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
    </Context>
    
    • redis配置

    下载jedis.jar,放到 $CATALINA_HOME/lib/ ,对应本次安装就是/usr/local/tomcat/lib

    # yum install redis
    # vim /etc/redis.conf
    bind 0.0.0.0
    # systemctl start redis
    

    放到 $CATALINA_HOME/conf/context.xml 中

    
    <Context>
    ...
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="redis://192.168.142.152:6379"
    sticky="false"
    sessionBackupAsync="false"
    lockingMode="uriPattern:/path1|/path2"
    requestUriIgnorePattern=".*.(ico|png|gif|jpg|css|js)$"
    transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
    />
    </Context>
    

    4. 总结

    • 通过多组实验,使用不同技术实现了session持久机制
    1. session绑定,基于IP或session cookie的。其部署简单,尤其基于session黏性的方式,粒度小,
      对负载均衡影响小。但一旦后端服务器有故障,其上的session丢失。
    2. session复制集群,基于tomcat实现多个服务器内共享同步所有session。此方法可以保证任意一
      台后端服务器故障,其余各服务器上还都存有全部session,对业务无影响。但是它基于多播实现
      心跳,TCP单播实现复制,当设备节点过多,这种复制机制不是很好的解决方案。且并发连接多的
      时候,单机上的所有session占据的内存空间非常巨大,甚至耗尽内存。
    3. session服务器,将所有的session存储到一个共享的内存空间中,使用多个冗余节点保存
      session,这样做到session存储服务器的高可用,且占据业务服务器内存较小。是一种比较好的解
      决session持久的解决方案。

    以上的方法都有其适用性。生产环境中,应根据实际需要合理选择。
    不过以上这些方法都是在内存中实现了session的保持,可以使用数据库或者文件系统,把session数据
    存储起来,持久化。这样服务器重启后,也可以重新恢复session数据。不过session数据是有时效性
    的,是否需要这样做,视情况而定。

  • 相关阅读:
    同步ajax请求
    Thinking in Java——笔记(11)
    Thinking in Java——笔记(10)
    Thinking in Java——笔记(9)
    Thinking in Java——笔记(8)
    Thinking in Java——笔记(7)
    Thinking in Java——笔记(6)
    Thinking in Java——笔记(5)
    Thinking in Java——笔记(4)
    Thinking in Java——笔记(3)
  • 原文地址:https://www.cnblogs.com/precipitation/p/14189213.html
Copyright © 2011-2022 走看看