玩转云文件存储

导语

腾讯云文件存储 CFS 终于可算发布了。在这之前我们已经有了本地硬盘、云硬盘、SSD 硬盘、对象 存储(COS)、归档存储等这么多种存储产品,为什么还需要一种新的产品呢?在应用场景说明文档中已经列举部分CFS常用的应用场景,但是其实CFS也可以用来解决一些长久以来的困扰。比如,CFS最突出的一个特点是可以同时挂载到多台CVM服务器上,每台服务都可以当本地硬盘来使用(实测读写速度比本地硬盘慢一点,但是多数场景下不成为瓶颈)。这就意味着,多台cvm上可以有一个目录从此可以实现全自动的文件实时同步。以往我们启动多台服务器做集群服务的时候,常常遇到最困难的一些文件同步问题从此就可以迎刃而解了。我们列举几个场景:

统一反向代理缓存

我有一个服务器集群,是使用nginx的回源特性,来对一个数据源做数据分发,并且在分发的时候会尝试在本机做一个文件缓存的:

代码语言:javascript
复制
proxy_temp_path   /proxy/proxy_temp_dir;   #指定临时文件目录
proxy_cache_path  /proxy/proxy_cache_dir levels=1:2 keys_zone=cache_one:150m inactive=3d max_size=10g;
#设置Web缓存区名称为cache_one,内存缓存为150MB,自动清除20天内没有被访问的文件硬盘缓存为10GB。

这样经常遇到的一个困扰就是各台服务器之间的缓存目录无法共享缓存的文件,因此不得不每台服务器都各自回源一次,又浪费数据源的带宽、给数据源增加不必要的访问压力,还浪费存储。现在有了CFS,我们就很容易让所有的服务器共享同一个proxy文件夹了: switch2CFS.sh

代码语言:javascript
复制
yum -y install nfs-utils
service nginx stop
if [ ! -d '/proxy_old' ]; then mv /proxy /proxy_old; fi
if [ ! -d '/proxy' ]; then mkdir /proxy; fi
mount -t nfs4 10.xxx.xxx.xxx:/ /proxy
if [ ! -d '/proxy/proxy_cache_dir' ]; then mkdir /proxy/proxy_cache_dir; fi
if [ ! -d '/proxy/proxy_temp_dir' ];then mkdir /proxy/proxy_temp_dir; fi
service nginx start

把上面的xxx替换成自己开通的CFS的ip,然后把这段脚本在每一台服务器依次运行一遍,所有的服务器的缓存目录就都收敛到一处了。 当然如果要切换回来也很容易: switch2localFS.sh

代码语言:javascript
复制
service nginx stop
umount /proxy
rm -rf /proxy
if [ -d '/proxy_old' ]; then mv /proxy_old /proxy; fi
if [ ! -d '/proxy/proxy_cache_dir' ]; then mkdir /proxy/proxy_cache_dir; fi
if [ ! -d '/proxy/proxy_temp_dir' ];then mkdir /proxy/proxy_temp_dir; fi
service nginx start

统一附件

很多系统,比如discuz、CMS等如果启动了多个实例做负载均衡,经常会出现被分配到A服务器的用户上传了附件,分配到B服务器的用户看到帖子和文章的时候却看不到图片。这是因为附件文件被传到了本地目录中,难以在多个服务器之间及时共享。

过往这类问题都要通过比较复杂的方式来尽量解决,比如用inotify触发rsync进行文件同步(别忘了删除文件也要同步),或者采用远程附件形式把文件FTP上传到COS等(目前的COS不支持直接FTP,因此还需要在本地搭建一个FTP代理)。而且这些操作都不是实时的,在附件比较大或者网络比较繁忙的的时候,仍然会有一个比较长的时间窗各个服务器上的文件无法同步,用户看到互相矛盾的信息。

但是有了CFS这个问题就简单多了。新建一个CFS并挂载到全部主机上,然后在后台管理界面把附件目录指向CFS上的一个目录,然后所有的服务器上的附件就都实现了实时同步。

比如在discuz上修改附件保存位置的后台配置项目是这里:

统一登录态

php等web服务经常把用户的回话状态(session)保存到文件系统中,这样在使用服务器集群的时候就会出现登录态不一致,在A服务器上登录过的用户,在B服务器上却被认为没有登录。

在以往,为了实现集群中的一组服务器上的登录状态共享,经常需要修改默认的会话逻辑,比如另外搭建或者采购一个memcache/redis等缓存服务来存储会话,或者干脆用数据库来存储会话。这样不但麻烦,而且为了避免这个存储会话的服务成为新的系统单点往往还要做更多的保障工作,比如做主从设计等等。

但是有了CFS以后,我们只要新建一个CFS并且挂载到全部主机上,然后修改php.ini文件中的 session.save_path = /tmp配置项,把回话保存路径指向同一个在CFS上的目录,这样一个人登录一台服务器,集群中所有的服务器旧都能立刻同步到信息。而且CFS本身是一个排除了单点风险的可靠服务。

统一web服务代码版本

一些采用了集群服务的系统经常需要反复更新代码逻辑,这样每次更改代码后,都要逐一发布到集群中的所有服务器上,这个过程如果手工操作很容易出错或者改漏,如果开发一个专业的运维系统来解决这样的问题成本不低。

但是有了CFS以后,我们只要把原来的代码拷贝进CFS,然后把所有服务器代码的目录指向CFS,代码立刻就能实现实时同步。

搭配弹性伸缩服用效果更佳

弹性伸缩服务可以按需为云上的系统提供恰到好处的计算和分发能力,但是 A.在遭遇系统扩容的时候,用旧镜像新生成的扩容服务器经常数据不是最新的,需要做额外的工作来同步 B. 在需要缩容的时候,如果在扩容出来的服务器上有新生成或者用户新上传的数据,需要做更多的数据同步工作收尾然后才能执行缩容。这样腾讯云默认的系统缩扩容就难以全自动的完成缩扩容所需要的全部工作了。

A问题也许还好一点,我们可以在服务器镜像中前置一个开机任务来追上新数据。B问题如果采用系统触发的缩容,连数据同步的机会都可能没有,除非自己主动监测缩容条件,自己迁移数据后,调缩容API来实现缩容。这样开发量也不小。

但是有了CFS以后,只要确保新生成和新上传的数据是保存在CFS上的,服务器可以随意的生成和销毁,不需要做什么额外的数据同步工作。

结语

CFS解决了集群服务的很多困扰多年的问题,实乃居家旅行,负载均衡、弹性伸缩之必备良药。

P.S. 以上有部分场景纯理论探讨,时间仓促没来得及实际验证,如有错漏敬请指出。