文章 78
评论 0
浏览 8356
4-Memcached

4-Memcached

4 Memcached

4.1 NoSQL介绍

NoSQL是对 Not Only SQL、非传统关系型数据库的统称。

NoSQL一词诞生于1998年,2009年这个词汇被再次提出指非关系型、分布式、不提供ACID的数据库设计模式。

随着互联网时代的到来,数据爆发式增长,数据库技术发展日新月异,要适应新的业务需求。

而随着移动互联网、物联网的到来,大数据的技术中NoSQL也同样重要。

数据库排名:https://db-engines.com/en/ranking

NoSQL 分类

  • Key-value Store k/v数据库
    • 性能好 O(1) , 如: redis、memcached
  • Document Store 文档数据库
    • mongodb、CouchDB
  • Column Store 列存数据库,Column-Oriented DB
    • HBase、Cassandra,大数据领域应用广泛
  • Graph DB 图数据库
    • Neo4j
  • Time Series 时序数据库
    • InfluxDB、Prometheus

4.2 Memcached

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

memcached 虽然没有像redis所具备的数据持久化功能,比如RDB和AOF都没有,但是可以通过做集群同步的方式,让各memcached服务器的数据进行同步,从而实现数据的一致性,即保证各memcached的数据是一样的,即使有任何一台 memcached 发生故障,只要集群中有一台memcached 可用就不会出现数据丢失,当其他memcached 重新加入到集群的时候,可以自动从有数据的memcached 当中自动获取数据并提供服务。

Memcached 借助了操作系统的 libevent 工具做高效的读写。libevent是个程序库,它将Linux的epoll、BSD类操作系统的kqueue等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥高性能。memcached使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能

Memcached 支持最大的内存存储对象为1M,超过1M的数据可以使用客户端压缩或拆分报包放到多个key中,比较大的数据在进行读取的时候需要消耗的时间比较长,memcached 最适合保存用户的session实现session共享

Memcached存储数据时, Memcached会去申请1MB的内存, 把该块内存称为一个slab, 也称为一个page

Memcached 支持多种开发语言,包括:JAVA,C,Python,PHP,C#,Ruby,Perl等

Memcached 官网:http://memcached.org/

4.3 Memcached 和 Redis 比较

clipboard.png

4.4 Memcached 工作机制

4.4.1 内存分配机制

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

Memcached采用了Slab Allocator机制来分配、管理内存。

  • Page:分配给Slab的内存空间,默认为1MB,分配后就得到一个Slab。Slab分配之后内存按照固定字节大小等分成chunk。

  • Chunk:用于缓存记录k/v值的内存空间。Memcached会根据数据大小选择存到哪一个chunk中,假设chunk有128bytes、64bytes等多种,数据只有100bytes存储在128bytes中,存在少许浪费。

    • Chunk最大就是Page的大小,即一个Page中就一个Chunk
  • Slab Class:Slab按照Chunk的大小分组,就组成不同的Slab Class, 第一个Chunk大小为 96B的Slab为Class1,Chunk 120B为Class 2,如果有100bytes要存,那么Memcached会选择下图中SlabClass 2 存储,因为它是120bytes的Chunk。Slab之间的差异可以使用Growth Factor 控制,默认1.25。
    clipboard.png

范例:查看Slab Class

[15:02:54 root@memcached ~]#memcached -u memcached -f 2 -vv
slab class   1: chunk size        96 perslab   10922
slab class   2: chunk size       192 perslab    5461
slab class   3: chunk size       384 perslab    2730
slab class   4: chunk size       768 perslab    1365
slab class   5: chunk size      1536 perslab     682
slab class   6: chunk size      3072 perslab     341
slab class   7: chunk size      6144 perslab     170
slab class   8: chunk size     12288 perslab      85
slab class   9: chunk size     24576 perslab      42
slab class  10: chunk size     49152 perslab      21
slab class  11: chunk size     98304 perslab      10
slab class  12: chunk size    196608 perslab       5
slab class  13: chunk size    524288 perslab       2
<27 server listening (auto-negotiate)
<28 server listening (auto-negotiate)

4.4.2 懒过期 Lazy Expiration

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

4.4.3 LRU

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

4.4.4 集群

Memcached集群,称为基于客户端的分布式集群,即由客户端实现集群功能,即Memcached本身不支持集群

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

4.5 安装和启动

官方安装说明

https://github.com/memcached/memcached/wiki/Install

4.5.1 yum安装

范例: CentOS 8 安装 memcached

[15:03:18 root@memcached ~]#yum info memcached
[15:05:04 root@memcached ~]#yum install -y memcached
[15:05:26 root@memcached ~]#rpm -ql memcached

[15:05:55 root@memcached ~]#cat /etc/sysconfig/memcached
PORT="11211"      #监听端口
USER="memcached"  #启动用户
MAXCONN="1024"     #最大连接数
CACHESIZE="64"     #最大使用内存
OPTIONS="-l 127.0.0.1,::1" #其他选项

[15:07:21 root@memcached ~]#grep -Ev "^#|^$" /usr/lib/systemd/system/memcached.service
[Unit]
Description=memcached daemon
Before=httpd.service
After=network.target
[Service]
EnvironmentFile=/etc/sysconfig/memcached
ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS
PrivateTmp=true
ProtectSystem=full
NoNewPrivileges=true
PrivateDevices=true
CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
[Install]
WantedBy=multi-user.target

[15:08:19 root@memcached ~]#getent passwd memcached 
memcached:x:992:990:Memcached daemon:/run/memcached:/sbin/nologin

[15:08:35 root@memcached ~]#systemctl start memcached.service 
[15:10:07 root@memcached ~]#pstree -p | grep memcached
           |-memcached(1814)-+-{memcached}(1815)
           |                 |-{memcached}(1816)
           |                 |-{memcached}(1817)
           |                 |-{memcached}(1818)
           |                 |-{memcached}(1819)
           |                 |-{memcached}(1820)
           |                 |-{memcached}(1821)
           |                 |-{memcached}(1822)
           |                 `-{memcached}(1823)
           
[15:10:32 root@memcached ~]#ss -ntlup | grep memcached
tcp     LISTEN   0        128            127.0.0.1:11211          0.0.0.0:*      users:(("memcached",pid=1814,fd=27))                                           
tcp     LISTEN   0        128                [::1]:11211             [::]:*      users:(("memcached",pid=1814,fd=28))
#修改端口绑定的IP为当前主机的所有IP
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
#OPTIONS="-l 127.0.0.1,::1"
OPTIONS=""

[15:11:37 root@memcached ~]#systemctl restart memcached.service 
[15:11:55 root@memcached ~]#ss -ntl
State     Recv-Q    Send-Q         Local Address:Port          Peer Address:Port    
LISTEN    0         128                  0.0.0.0:11211              0.0.0.0:*       
LISTEN    0         128                  0.0.0.0:111                0.0.0.0:*       
LISTEN    0         128                  0.0.0.0:22                 0.0.0.0:*       
LISTEN    0         128                     [::]:11211                 [::]:*       
LISTEN    0         128                     [::]:111                   [::]:*       
LISTEN    0         128                     [::]:22                    [::]:*

4.5.2 编译安装

#安装脚本

install_dir='/usr/local/'
yum install -y gcc libevent-devel
rpm -q wget &>/dev/null || yum install -y wget
wget http://memcached.org/files/memcached-1.6.9.tar.gz
tar xvf memcached-1.6.9.tar.gz
cd memcached-1.6.9
[ -d $install_dir ] || mkdir -p $install_mkdir

./configure --prefix=${install_dir}/memcached

make && make install

echo "PATH=${install_mkdir}/memcached/bin:\$PATH" >/etc/profile.d/memcached.sh

id memcached &>/dev/null || useradd -r -s /sbin/nologin memcached
cat >/etc/sysconfig/memcached<<EOF
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
#OPTIONS="-l 127.0.0.1,::1"
OPTIONS=""
EOF
cat >/lib/systemd/system/memcached.service<<EOF
[Unit]
Description=memcached daemon
Before=httpd.service
After=network.target
[Service]
EnvironmentFile=/etc/sysconfig/memcached
ExecStart=${install_dir}/memcached/bin/memcached -p \${PORT} -u \${USER} -m \${CACHESIZE} -c \${MAXCONN} \$OPTIONS
PrivateTmp=true
ProtectSystem=full
NoNewPrivileges=true
PrivateDevices=true
CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
echo "安装完成"

4.5.3 memcached 启动程序说明

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

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

4.6 使用 memcached

4.6.1 memcached 开发库和工具

与memcached通信的不同语言的连接器。libmemcached提供了C库和命令行工具。

范例: 查看memcached相关包

[15:36:27 root@centos8 ~]#yum list "*memcached*"

协议

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

[15:36:47 root@centos8 ~]#dnf info libmemcached
[15:38:14 root@centos8 ~]#yum install libmemcached
[15:38:01 root@centos8 ~]#memstat --servers=192.168.10.84

4.6.2 memcached 操作命令

帮助文档:

[root@centos8 ~]#cat /usr/share/doc/memcached/protocol.txt

五种基本 memcached 命令执行最简单的操作。这些命令和操作包括:

  • set
  • add
  • replace
  • get
  • delete
#前三个命令是用于操作存储在 memcached 中的键值对的标准修改命令,都使用如下所示的语法:
command    

#参数说明如下:
command set/add/replace
key     key 用于查找缓存值
flags     可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息
expiration time     在缓存中保存键值对的时间长度(以秒为单位,0 表示永远)
bytes     在缓存中存储的字节点
value     存储的值(始终位于第二行)
#增加key,过期时间为秒,bytes为存储数据的字节数
add key flags exptime bytes

范例:

[15:40:01 root@centos8 ~]#telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
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
delete mykey
DELETED
get mykey
END
flush_all
OK
get mykey
END
quit

4.6.3 python 语言连接 memcached

4.6.3.1 范例: python3 测试代码

[15:48:04 root@centos8 ~]#cat m2.py
#!/usr/bin/env python
import memcache
m = memcache.Client(['127.0.0.1:11211'], debug=True)
for i in range(10):
   m.set("key%d" % i,"v%d" % i)
   ret = m.get('key%d' % i)
   print("%s" % ret)
[15:48:09 root@centos8 ~]#python3 m2.py 
v0
v1
v2
v3
v4
v5
v6
v7
v8
v9

4.6.3.2 范例: python2 测试代码

[root@centos7 ~]#yum -y install python-memcached
[root@centos7 ~]#cat m2.py
#!/usr/bin/env python
#coding:utf-8
import memcache
m = memcache.Client(['127.0.0.1:11211'], debug=True)
for i in range(10):
m.set("key%d" % i,"v%d" % i)
ret = m.get('key%d' % i)
print ret
[root@centos7 ~]#python m2.py
v0
v1
v2
v3
v4
v5
v6
v7
v8
v9

4.7 memcached 集群部署架构

4.7.1 基于 magent 的部署架构

Magent是google开发的项目,应用端通过负载均衡服务器连接到magent,然后再由magent代理用户应用请求到memcached处理,底层的memcached为双主结构会自动同步数据,本部署方式存在magent单点问题,因此需要两个magent做高可用。

clipboard.png
项目站点:https://code.google.com/archive/p/memagent/

此项目过于陈旧,且不稳定,当前已经废弃

4.7.2 Repcached 实现原理

项目站点:http://repcached.sourceforge.net/

在 master上可以通过 -X 选项指定 replication port(默认为11212/tcp),在 slave上通过 -x 指定复制的master并连接,事实上,如果同时指定了 -x/-X, repcached先会尝试连接对端的master,但如果连接失败,它就会用 -X参数来自己 listen(成为master);如果 master坏掉, slave侦测到连接断了,它会自动 listen而成为 master;而如果 slave坏掉,master也会侦测到连接断开,它就会重新 listen等待新的 slave加入。

从这方案的技术实现来看,其实它是一个单 master单 slave的方案,但它的 master/slave都是可读写的,而且可以相互同步,所以从功能上看,也可以认为它是双机 master-master方案

4.7.3 简化后的部署架构

magent已经有很长时间没有更新,因此可以不再使用magent,直接通过负载均衡连接到memcached,仍然有两台memcached做高可用,repcached版本的memcached之间会自动同步数据,以保持数据一致性,即使其中的一台memcached故障也不影响业务正常运行,故障的memcached修复上线后再自动从另外一台同步数据即可保持数据一致性。

clipboard.png

4.7.4 部署repcached

[15:55:52 root@centos7 ~]#yum -y install gcc libevent libevent-devel
[16:02:35 root@centos7 ~]#wget http://sourceforge.net/projects/repcached/files/repcached/2.2.1-1.2.8/memcached-1.2.8-repcached-2.2.1.tar.gz/download
[16:02:50 root@centos7 ~]#tar xf memcached-1.2.8-repcached-2.2.1.tar.gz
[16:02:56 root@centos7 ~]#cd memcached-1.2.8-repcached-2.2.1/
[16:02:59 root@centos7 memcached-1.2.8-repcached-2.2.1]#./configure --prefix=/usr/local/repcached --enable-replication
[16:04:07 root@centos7 memcached-1.2.8-repcached-2.2.1]#make   #报错如下

clipboard.png

解决办法:

[16:04:10 root@centos7 memcached-1.2.8-repcached-2.2.1]#vim memcache
56 #ifndef IOV_MAX
57 #if defined(__FreeBSD__) || defined(__APPLE__)
58 # define IOV_MAX 1024
59 #endif
60 #endif
#改为如下内容,即删除原有的原第57,59行
56 #ifndef IOV_MAX
57 # define IOV_MAX 1024
58 #endif

再次编译安装:

[16:07:22 root@centos7 memcached-1.2.8-repcached-2.2.1]#make && make install
[16:07:05 root@centos7 ~]#tree /usr/local/repcached/
/usr/local/repcached/
├── bin
│   ├── memcached
│   └── memcached-debug
└── share
└── man
└── man1
└── memcached.1

4 directories, 3 files

4.7.5 验证是否可执行

[16:07:43 root@centos7 ~]#echo 'PATH=/usr/local/repcached/bin:$PATH' >/etc/profile.d/repcached.sh
[16:08:52 root@centos7 ~]#memcached -h
memcached 1.2.8
repcached 2.2.1
-p       TCP port number to listen on (default: 11211)
-U       UDP port number to listen on (default: 11211, 0 is off)
-s      unix socket path to listen on (disables network support)
-a      access mask for unix socket, in octal (default 0700)
.....

4.7.6 启动 memcached

4.7.6.1 server1 相关操作

#创建用户
[16:09:46 root@centos7 ~]#useradd -r -s /sbin/nologin memcached
#后台启动
#-x 192.168.10.72为对端memcached的地址
[16:18:34 root@centos7 ~]#memcached -d -m 128 -p 11211 -u memcached -c 128 -x 192.168.10.72
[16:19:51 root@centos7 ~]#ss -ntl
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port
LISTEN     0      128            *:111                        *:*
LISTEN     0      128            *:22                         *:*
LISTEN     0      100    127.0.0.1:25                         *:*
LISTEN     0      128            *:11211                      *:*
LISTEN     0      128         [::]:111                     [::]:*
LISTEN     0      128         [::]:22                      [::]:*
LISTEN     0      100        [::1]:25                      [::]:*
LISTEN     0      128         [::]:11211                   [::]:*

4.7.6.2 server2 相关操作

[16:18:31 root@centos7 ~]#memcached -d -m 128 -p 11211 -u memcached -c 128 -x 192.168.10.71
[16:19:42 root@centos7 ~]#ss -ntl
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port
LISTEN     0      128            *:22                         *:*
LISTEN     0      100    127.0.0.1:25                         *:*
LISTEN     0      128            *:11211                      *:*
LISTEN     0      128            *:111                        *:*
LISTEN     0      128         [::]:22                      [::]:*
LISTEN     0      100        [::1]:25                      [::]:*
LISTEN     0      128         [::]:11211                   [::]:*
LISTEN     0      128         [::]:111                     [::]:*

4.7.7 连接到 memcached 验证数据

4.7.7.1 shell 命令测试

#在第一台memcached上创建数据
[16:22:05 root@centos7 ~]#telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
add name 0 0 5
zhang
STORED
get name
VALUE name 0 5
zhang
#到另外一台memcached服务器验证是否有同步过来的数据
[16:22:39 root@centos7 ~]#telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get name
VALUE name 0 5
zhang
END
set age 0 0 2
20
STORED
#在第一台memcached上验证实现双向复制
get age
VALUE age 0 2
20

标题:4-Memcached
作者:Carey
地址:HTTPS://zhangzhuo.ltd/articles/2021/03/20/1616230496410.html

生而为人

取消