@[TOC](Tomcat memcached和msm 小节5)
NoSQL
NoSQL是对非SQL、非传统关系型数据库的统称。
NoSQL一词诞生于1998年,2009年这个词汇被再次提出指非关系型、分布式、不提供ACID的数据库设计模式。
随着互联网时代的到来,数据爆发式增长,数据库技术发展日新月异,要适应新的业务需求。
随着移动互联网、物联网的到来,大数据的技术中NoSQL也同样重要。
分类
- Key-value Store
- redis、momcached
- Document Store
- mongodb、CouchDB
- Column Store列存数据库,Column-Oriented DB
- HBase、CAssandra
- Graph DB
- Neo4j
- Time Series时序数据库
- influxDB
Memcached
Memcached只支持能序列化的数据类型,不支持持久化,基于Key-Value的内存缓存系统。
内存分配机制
应用程序运行需要使用内存存储数据,但对于一个缓存系统来说,申请内存、释放内存将十分频繁,非常容易导致大量内存碎片,最后导致无连续可用内存可用。
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 Class2存储,因为它是120bytes的Chunk。Slab之间的差异可以使用Growth Factor控制,默认1.25。
懒过期Lazy Expiration
memcached不会监视数据是否过期,而是在取数据时才看是否过期,过期的把数据有效期限标识为O,并不清除该数据。以后可以覆盖该位置存储其它数据。
LRU
当内存不足时,memcached会使用LRU (Least Recently Used)机制来查找可用空间,分配给新纪录使用。
集群
Memcached集群,称为基于客户端的分布式集群。
Memcached集群内部并不互相通信,一切都需要客户端连接到Memcached服务器后自行组织这些节点,并决定数据存储的节点。
安装
t1和t2
]# yum install memcached -y
]# 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
#前台显示看效果
]# memcached -u memcached -p 11211 -f 1.25 -vv
#-U表示设置UDP监听端口,0表示禁用UDP
]# memcached -u memcached -p 11211 -f 2 -U 0 -vv
修改memcached运行参数,可以使用下面的选项修改/etc/sysconfig/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
]# memcached -u memcached -p 11211 -f 2 -U 0 -vv
再开一个窗口
]# # yum install memcached -y
协议
]# telnet 127.0.0.1 11211
stats <--状态
add mykey 1 60 4 <--add增加一个值、增加key、1标记、60秒后过期、4key对应的value值是几个字节
abcd <--4个字节
STORED <--存起来了
get mykey <--去取
VALUE mykey 1 4
abcd
END
set mykey 1 40 5 <--set重置
12345
STORED
get mykey
VALUE mykey 1 5
12345
END
quit <--退出
Connection closed by foreign host
add key flages exptime bytes,增加key,过期时间为妙,bytes为存储数据的字节数
session共享服务器
msm
msm (memcached session manager)提供将Tomcat的session保持到memcached或redis的程序,可以实现高可用。
目前项目托管在Github,https:l/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)
安装
t1和t2
]# cd /usr/local/tomcat/
]# vim conf/server.xml
#里面的集群不要了、所以直接删掉
]# rm -rf /data/webapps/ROOT/WEB-INF/web.xml
配置
特别注意,t1配置中为failoverNodes="n1",t1配置中为failoverNodes="n2"
]# vim conf/context.xml
<Context>
...
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1: 192.168.37.14:11211,n2:192.168.37.15:11211"
failoverNodes="n2"
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.
msm包和kryo包(序列化)内容放到'/lib'下
]# pwd
/usr/local/tomcat
]# cd /lib
#按照时间排序、可以看到上传了11个
]# ll -t
-rw-r--r-- 1 root root 72265 8月 26 21:35 reflectasm-1.11.9.jar
-rw-r--r-- 1 root root 55684 8月 26 21:35 objenesis-2.6.jar
-rw-r--r-- 1 root root 38372 8月 26 21:35 msm-kryo-serializer-2.3.2.jar
-rw-r--r-- 1 root root 5923 8月 26 21:35 minlog-1.3.1.jar
-rw-r--r-- 1 root root 126366 8月 26 21:35 kryo-serializers-0.45.jar
-rw-r--r-- 1 root root 285211 8月 26 21:35 kryo-3.0.3.jar
-rw-r--r-- 1 root root 53259 8月 26 21:35 asm-5.2.jar
-rw-r--r-- 1 root root 473774 8月 26 21:35 spymemcached-2.12.3.jar
-rw-r--r-- 1 root root 10826 8月 26 21:35 memcached-session-manager-tc8-2.3.2.jar
-rw-r--r-- 1 root root 167294 8月 26 21:35 memcached-session-manager-2.3.2.jar
-rw-r--r-- 1 root root 586620 8月 26 21:35 jedis-3.0.0.jar
...
]# ../bin/shutdown.sh
]# ../bin/startup.sh
]# systemctl start memcached
]# systemctl enable memcached
sticky模式
原理
当请求结束时Tomcat的session会送给memcached备份。即Tomcat session为主session,memcached session为session,使用memcached相当于备份了一份Session。
查询Session时Tomca会优先使用自己内存的Session,Tomcat通过jemRoute发现不是自己的Session,便从memcached中找到该Seesion,更新本机Session,请求完成更新memcached。
部署
t1和m1部署在一台主机上,t2和m2部署在同一台。
实验
如果配置成功,可以在logs/catalina.out中看到下面的内容
#可以看监控日志
]# cat /usr/local/tomcat/logs/catalina.out
27-Aug-2022 00:40:59.098 INFO [t2.123.com-startStop-1] de.javakaffee.web.msm.MemcachedSessionService.startInternal --------
- finished initialization:
- sticky: true
- operation timeout: 1000
- node ids: [n1]
- failover node ids: [n2]
- storage key prefix: null
- locking mode: null (expiration: 5s)
--------
配置成功后,网页访问一下,页面中看到了Session。然后运行下面的Python程序,就可以看到是否存储到了memcached中了。
nginx
]# vim /etc/nginx/nginx.conf
...
#此处五行(添加)
upstream tomcats {
#ip_hash; <--注释掉此行
server t1.123.com:8080;
server t2.123.com:8080;
}
...
#重启服务
]# systemctl restart nginx
#查看端口是否开启
]# ss -ntlp|grep nginx
配置成功后,网页访问一下,页面中看到了Session。
然后打开PyCharm,运行下面程序,就可以看到是否存储到了memcached中。
non-sticky模式
原理
从msm1.4.0之后开始支持non-sticky模式。
Tomcat session为中转Session,n1为主session,n2为备session。产生的新的Session会发送给主、备memcached,并清除本地Session。
n1下线,n2转正。n1再次上线,n2依然时主Session存储节点。
memcached配置
t1和t2
放到'/conf/contesxt.xml'中
]# pwd
/usr/local/tomcat
]# vim conf/context.xml
<Context>
...
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:192.168.37.14:11211,n2:192.168.37.15: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>
]# bin/shutdown.sh
]# bin/startup.sh
Pycharm
redis配置
下载jedis.jar,放到$CATALINA_HOME/lib/, 对应本次安装就是/usr/local/taomcat/lib
t1
]# yum install redis -y
]# vim /etc/redis.conf
...
#bind 127.0.0.1
bind 0.0.0.0
]# systemctl start redis
#查看redis端口是否启动
]# ss -ntlp|grep redis
LISTEN 0 128 *:6379 *:* users:(("redi-server",pid=10908,fd=4))
t1、t2
]# pwd
/usr/local/tomcat
]# vim conf/context.xml
...
<Context>
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="redis://192.168.37.14: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>
...
]# bin/shutdown.sh
]# bin/startup.sh
...
redis-desktop-manager-0.8.8.384
总结
通过多组使用,使用不同技术实现了session持久机制
- session绑定,基于IP或session cookie的。其部署简单,尤其基于session黏性的方式,粒度小,对负载均衡影响小。但一旦后端服务器有故障,其上的session丢失。
- session复制集群,基于tomcat实现多个服务器内共享同步所有session。此方法可以保证任意一台后端服务器故障,其余各服务器上还都存有全部session,对业务无影响。但是它基于多播实现心跳,TCP单播实现复制,当设备节点过多,这种复制机制不是很好的解决方案。且并发连接多的时候,单机上的所有session占据的内存空间非常巨大,甚至耗尽内存。
- session服务器,将所有的session存储到一个共享的内存空间中,使用多个冗余节点保存session,这样做到session存储服务器的高可用,且占据业务服务器内存较小,是一种比较好的解决session持久的解决方案。
以上的方法都有其适用性。生产环境中,应根据实际需要合理选择。
不过以上这些方法都是在内存中实现了session的保持,可以使用数据库或者文件系统,把session数据库储存起来,持久化。这样服务器重启后,也可以重新恢复session数据。不过session数据时有时效性的,是否需要这样做,视情况而定。