无论好坏,云中键值存储的一个主要用例是会话缓存。这些对象是短暂的,经常更新的,与用户登录会话关联的大型数据块。非结构化数据和生存时间限制使其不适合作为主数据库。
网站所有者通常会设置一个 memcached 实例来处理会话。我们将重点关注会话数据,但是该实例可以同时处理其他数据。
假设您有一个网站,它已经从单个 droplet 发展起来。您有一个每月 20 美元的实例,其中 3.5G 的 RAM 专用于 memcached(尽管我们建议您运行多个实例,以防万一一个实例出现故障!)。您最近注意到,用户无法每天保持登录状态,并且您的数据库使用量正在上升。
对于许多会话实现,如果会话对象消失,用户将注销或数据库将遭受大量打击以重新生成它。因此,重要的是要将会话保留在它们有用的时间内。
Extstore 需要将对象的键和元数据保存在 RAM 中,同时将值指向存储。这对于小型对象来说不太合适。会话数据可能会变得相当大,所以让我们先检查一下。
$ echo "stats slabs" | nc localhost 11211 | grep -E "total_pages|chunk_size"
[... snip ...]
STAT 26:chunk_size 27120
STAT 26:total_pages 321
STAT 27:chunk_size 33904
STAT 27:total_pages 2936
STAT 28:chunk_size 42384
STAT 28:total_pages 157
[... snip ...]
通过快速检查,我们可以看到,分配的大部分内存最终都用于使用 26k-42k 内存的对象,其中大部分为 32k。即使在极端情况下,memcached 中的键和元数据也不能超过 300 字节,因此大部分空间都是项目值。非常适合 extstore!(尽管是人为的)
您可以并且应该查看或绘制来自 stats items
和 stats slabs
的计数器。在这种情况下,我们可以发现 slab 类 26、27 和 28 也具有很高的驱逐计数。我们过早地丢弃了会话!
目前,我们通过一个 20 美元的 droplet 获得了 3.5G 的 RAM 缓存。截至撰写本文时,一个 10 美元的 droplet 附带 2G 的 RAM 和 50G 的 SSD 支持的磁盘空间。让我们尝试将可用缓存空间增加三倍,而成本减半。
由于 extstore 仍然是新功能,您可能需要自己构建 memcached 来启用它。当您阅读本文时,这可能不再需要,因此请检查 memcached -h
以查看是否支持 extstore,然后再手动构建任何内容。
在本例中,我们使用来自 DigitalOcean 的 Ubuntu 18.04 64 位 Droplet。请根据您的喜好对这些二进制文件和配置进行打包、快照或管理。
首先,获取最新的 tarball。我们应该修复重定向;)
d@blogbox:~$ wget https://memcached.org.cn/latest
[... snip ...]
latest 100%[=========================>] 454.27K --.-KB/s in 0.005s
2018-08-14 04:46:27 (96.5 MB/s) - ‘latest’ saved [465169/465169]
d@blogbox:~$ tar -zxvf latest
d@blogbox:~$ ls
latest memcached-1.5.10
d@blogbox:~$ rm latest
接下来,我们获取一些依赖项并编译守护进程。请注意,在基于 Red Hat 的发行版(CentOS 等)上,您可能需要安装一些 Perl 模块才能运行测试。
d@blogbox:~$ cd memcached-1.5.10/
d@blogbox:~/memcached-1.5.10$ sudo apt-get install build-essential libevent-dev
Reading package lists... Done
Building dependency tree... 50%
Reading state information... Done
[... snip ...]
Do you want to continue? [Y/n] y
[... snip ...]
d@blogbox:~/memcached-1.5.10$ ./configure --enable-extstore
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
[... snip ...]
configure: creating ./config.status
config.status: creating Makefile
config.status: creating doc/Makefile
config.status: creating config.h
config.status: executing depfiles commands
d@blogbox:~/memcached-1.5.10$ make
[... snip ...]
Leaving directory '/home/d/memcached-1.5.10'
make[1]: Leaving directory '/home/d/memcached-1.5.10'
d@blogbox:~/memcached-1.5.10$
可选地,运行测试。注意在 1.5.10 中,在 Ubuntu 18.04 上,t/lru-maintainer.t 可能会因竞争条件而失败。这已经修补,将在 1.5.11 中修复。
d@blogbox:~/memcached-1.5.10$ make test
[ might fail on t/lru-maintainer.t ]
现在,我们将二进制文件安装到 /usr/local 中。您可以在配置步骤中使用 --prefix
更改此设置。
d@blogbox:~/memcached-1.5.10$ sudo make install
源 tarball 附带 systemd 服务脚本和配置文件。让我们安装它们。请参阅以下内容以了解对文件的某些编辑。
d@blogbox:~/memcached-1.5.10$ sudo cp scripts/memcached.service /etc/systemd/system/
d@blogbox:~/memcached-1.5.10$ sudo mkdir /etc/sysconfig
d@blogbox:~/memcached-1.5.10$ sudo cp scripts/memcached.sysconfig /etc/sysconfig/memcached
d@blogbox:~/memcached-1.5.10$ sudo vi /etc/systemd/system/memcached.service
d@blogbox:~/memcached-1.5.10$ sudo vi /etc/sysconfig/memcached
编辑 /etc/systemd/system/memcached.service 中的“ExecStart”行,使其看起来像
ExecStart=/usr/local/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS
我们所做的只是在路径中添加“/local/”。
最后,使用类似于以下内容的 /etc/sysconfig/memcached
# These defaults will be used by every memcached instance, unless overridden
# by values in /etc/sysconfig/memcached.
USER="nobody"
MAXCONN="1024"
CACHESIZE="1500"
OPTIONS="-l 127.0.0.1 -o ext_path=/tmp/extstore:10G,ext_item_size=512"
# The PORT variable will only be used by memcached.service, not by
# memcached@xxxxx services, which will use the xxxxx
PORT="11211"
最后,启用并启动服务
d@blogbox:~/memcached-1.5.10$ sudo systemctl enable memcached
Created symlink /etc/systemd/system/multi-user.target.wants/memcached.service →
/etc/systemd/system/memcached.service.
d@blogbox:~/memcached-1.5.10$ sudo systemctl start memcached
d@blogbox:~/memcached-1.5.10$ ps aux | grep -i memcached
nobody 10069 0.0 0.3 1723160 7152 ? Ssl 05:32 0:00
/usr/local/bin/memcached -p 11211 -u nobody -m 1024 -c 1024 -l 127.0.0.1 -o
ext_path=/tmp/extstore:10G,ext_item_size=512
d 10100 0.0 0.0 14856 1048 pts/1 S+ 05:33 0:00 grep --color=auto -i memcached
d@blogbox:~/memcached-1.5.10$
然后...您就完成了!您现在已使用 1.5G 的 RAM 和 10G 的磁盘支持存储配置了 memcached。我们还告诉它允许将任何大于 512 字节的对象刷新到磁盘。
您可以(也应该!)根据自己的用例进行实验。也许您想将缓存分散到更多节点以提高可靠性,也许您的会话更小(因此需要更多 RAM)等等。没有硬性规定。
不太可能。Memcached 不会立即将大型对象刷新到磁盘:只要有可能,它们就会保留在 RAM 中。实际上,最新的对象也是“最热的”,经常被读取和覆盖。即使磁盘比 RAM 多 10 倍,9/10 的读写操作也可能保留在 RAM 中。
作为额外的好处,当对象被覆盖、删除或因 TTL 而过期时,它们不会造成任何磁盘 I/O。即使对于云实例有限的 I/O,这也能很好地扩展。
通过本演练,我们能够将理论网站会话缓存扩展 3 倍,成本降低一半。虽然这不能涵盖所有用例,但它可以快速确定并廉价地进行实验。
更详细的文档可在 维基页面 上找到。