接着上篇博文,上篇博文是讲如何部署 MooseFS 的,部署完毕之后就要涉及到后续的使用了。在使用过程中,肯定会遇到一些故障和性能瓶颈。此时,我们就需要去操心 MooseFS 的管理、维护和优化工作了。
本篇就围绕上面提到的三个方面,介绍 MooseFS 更深入的一些知识。
一、高级功能
1、副本
副本,在MFS中也被称为目标(Goal),它是指文件被复制的份数,设定目标值后可以通过mfsgetgoal命令来证实,也可以通过mfssetgoal命令来改变设定。
[root@mfs-client ~]# cd /mfsdata/ [root@mfs-client mfsdata]# dd if=/dev/zero of=/mfsdata/test.file bs=1M count=200 200+0 records in 200+0 records out 209715200 bytes (210 MB) copied, 9.1094 s, 23.0 MB/s [root@mfs-client mfsdata]# mfsgetgoal test.file test.file: 1 [root@mfs-client mfsdata]# mfssetgoal 3 test.file test.file: 3 [root@mfs-client mfsdata]# mfsgetgoal test.file test.file: 3
补充:
用mfsgetgoal r和mfssetgoal r同样的操作可以对整个树形目录递归操作
[root@mfs-client mfsdata]# mkdir dir/dir1/dir2/dir3 -p [root@mfs-client mfsdata]# touch dir/file1 [root@mfs-client mfsdata]# touch dir/dir1/file2 [root@mfs-client mfsdata]# touch dir/dir1/dir2/file3 [root@mfs-client mfsdata]# mfsgetgoal -r dir dir: files with goal 1 : 3 directories with goal 1 : 4 [root@mfs-client mfsdata]# mfssetgoal -r 3 dir dir: inodes with goal changed: 7 inodes with goal not changed: 0 inodes with permission denied: 0
实际的拷贝份数可以通过mfscheckfile 和 mfsfileinfo 命令来证实,例如:
[root@mfs-client mfsdata]# mfscheckfile test.file test.file: chunks with 1 copy: 4 [root@mfs-client mfsdata]# mfsfileinfo test.file test.file: chunk 0: 00000000000000D2_00000001 / (id:210 ver:1) copy 1: 172.16.100.6:9422 chunk 1: 00000000000000D3_00000001 / (id:211 ver:1) copy 1: 172.16.100.7:9422 chunk 2: 00000000000000D4_00000001 / (id:212 ver:1) copy 1: 172.16.100.6:9422 chunk 3: 00000000000000D5_00000001 / (id:213 ver:1) copy 1: 172.16.100.7:9422
需要注意的是,一个包含数据的零长度的文件,尽管没有设置为非零的目标(the non-zero goal),但是在使用命令查询时将返回一个空值
[root@mfs-client mfsdata]# touch a [root@mfs-client mfsdata]# mfscheckfile a a: [root@mfs-client mfsdata]# mfsfileinfo a a:
2、回收
一个删除文件能够存放在一个"垃圾箱"的时间就是一个隔离时间,这个时间可以用 mfsgettrashtime 命令来验证,也可以用 mfssettrashtime 命令来设置。例如:
[root@mfs-client mfsdata]# mfsgettrashtime test.file test.file: 86400 [root@mfs-client mfsdata]# mfssettrashtime 0 test.file test.file: 0 $ mfsgettrashtime /mnt/mfs-test/test1 /mnt/mfs-test/test1: 0
这些工具也有个递归选项-r,可以对整个目录树操作,例如:
[root@mfs-client mfsdata]# mfsgettrashtime -r dir dir: files with trashtime 86400 : 3 directories with trashtime 86400 : 4 [root@mfs-client mfsdata]# mfssettrashtime -r 0 dir dir: inodes with trashtime changed: 7 inodes with trashtime not changed: 0 inodes with permission denied: 0 [root@mfs-client mfsdata]# mfsgettrashtime -r dir dir: files with trashtime 0 : 3 directories with trashtime 0 : 4
时间的单位是秒(有用的值有:1小时是3600秒,24 86400秒,1 604800秒)。就像文件被存储的份数一样, 为一个目录 设定存放时间是要被新创建的文件和目录所继承的。数字0意味着一个文件被删除后, 将立即被彻底删除,在想回收是不可能的
删除文件可以通过一个单独安装 MFSMETA 文件系统。特别是它包含目录 / trash (包含任然可以被还原的被删除文件的信息)和 / trash/undel (用于获取文件)。只有管理员有权限访问MFSMETA(用户的uid 0,通常是root)。
在开始mfsmount进程时,用一个-m或-o mfsmeta的选项,这样可以挂接一个辅助的文件系统MFSMETA,这么做的目的是对于意外的从MooseFS卷上删除文件或者是为了释放磁盘空间而移动的文件而又此文件又过去了垃圾文件存放期的恢复,例如:
mfsmount -m /mnt/mfsmeta
需要注意的是,如果要决定挂载mfsmeta,那么一定要在 mfsmaster 的 mfsexports.cfg 文件中加入如下条目:
* . rw
原文件中有此条目,只要将其前的#去掉就可以了。
否则,你再进行挂载mfsmeta的时候,会报如下错误:
mfsmaster register error: Permission denied
下面将演示此操作:
$ mfssettrashtime 3600 /mnt/mfs-test/test1 /mnt/mfs-test/test1: 3600
从"垃圾箱"中删除文件结果是释放之前被它站用的空间(删除有延迟,数据被异步删除)。在这种被从"垃圾箱"删除的情况下,该文件是不可能恢复了。
可以通过mfssetgoal工具来改变文件的拷贝数,也可以通过mfssettrashtime工具来改变存储在"垃圾箱"中的时间。
在 MFSMETA 的目录里,除了trash和trash/undel两个目录外,还有第三个目录reserved,该目录内有已经删除的文件,但却有一直打开着。在用户关闭了这些被打开的文件后,reserved目录中的文件将被删除,文件的数据也将被立即删除。在reserved目录中文件的命名方法同trash目录中的一样,但是不能有其他功能的操作。
3、快照
MooseFS系统的另一个特征是利用mfsmakesnapshot工具给文件或者是目录树做快照,例如:
$ mfsmakesnapshot source ... destination
Mfsmakesnapshot 是在一次执行中整合了一个或是一组文件的拷贝,而且任何修改这些文件的源文件都不会影响到源文件的快照, 就是说任何对源文件的操作,例如写入源文件,将不会修改副本(或反之亦然)。
文件快照可以用mfsappendchunks,就像MooseFS1.5中的mfssnapshot一样,,作为选择,二者都可以用。例如:
$ mfsappendchunks destination-file source-file ...
当有多个源文件时,它们的快照被加入到同一个目标文件中(每个chunk的最大量是chunk)。五、额外的属性文件或目录的额外的属性(noowner, noattrcache, noentrycache),可以被mfsgeteattr,mfsseteattr,mfsdeleattr工具检查,设置,删除,其行为类似mfsgetgoal/mfssetgoal or或者是mfsgettrashtime/mfssettrashtime,详细可见命令手册。
二、综合测试
1、破坏性测试
a、模拟MFS各角色宕机测试
b、mfs 灾难与恢复各种场景测试
2、性能测试
针对 MooseFS 的性能测试,我这边也没有详细去做。通过伟大的互联网,我找到了几位前辈,针对 MooseFS 所做的详细性能测试,这里我就贴出来展示一下。
1、基准测 上篇文章主要介绍了我开源在Github上的图片剪裁库(ImageCropper)的基本特性和用法,从本文开始,慢慢介绍一些开发图片剪裁应用中涉及的知识点和技术。 其实Android系统本身也提供了图片剪裁的模块,我们可以直接通过Intent来调用系统的图片剪裁功能,本文我们就先了解一下系统自带的图片剪裁功能是如何调用的吧。 得到被剪裁图片的URL地址 既然是图片剪裁,就一定要有被剪裁的图片,由于图片数据一般很大,为了防止内存溢出,普通APP与Android系统图片剪裁应用之间是通过URL来传递图片地址的。这个URL与我们常说见的网络URL不一样,它并不是HTTP开头,而是以file或者content开头的字符串,例如: 这里,我们首先介绍获取图片URL的方法: (1) 从SDCard中得到图片的URL 假设知道图片存放的路径位于"/sdcard/test.jpg",那么,可以通过下面这种方式来得到URL: 当然,如果图片是从网络获取的,并不存在于sdcard中,则可以先保存一份临时文件到sdcard中,再通过上述方法得到URL。 注:通过这种方式得到的URL,一般以"file://"开头。 (2) 从多媒体数据库中得到图片的URL Android系统会在后台定期扫描存储在系统中的多媒体文件,如:音乐、图片和视频等,相关的信息会存放在系统的多媒体数据库中,位于/data/data/com.android.providers.media/databases中,我们可以通过检索该数据库得到图片的URL(例如:通过检索数据库得到系统最后一次添加/修改的照片URL),也可以通过Intent.ACTION_PICK来调用系统的图片选择器来选择一张图片,图片选择器会将图片的URL地址放入Intent的data中返回。 后者的应用更多一些,我们主要介绍一下后者,即通过Intent.ACTION_PICK来得到图片URL地址,方法如下: 注:通过这种方式得到的URL,一般以"content://media"开头。 (3) 调用系统的相机拍一张照片 当然,被剪裁的图片也可以是通过Camera拍摄的一张照片,方法如下: 通过代码你可能已经注意到了,其实这种方式得到的图片URL,与第一种方式是一样的,通过图片的存储路径转化过来的,只不过传递给了系统Camera应用中。 2. 通过Intent调用系统的图片剪裁功能 有了图片的URL,调用系统的图片剪裁就很简单了,只需要构建一个Intent对象,并设置相关参数即可,用法示例如下: 3. 小结 注意添加读写SDCard的权限: 关于调用系统的图片剪裁应用就介绍到这儿了,有任何疑问欢迎留言或者来信lujun.hust@gmail.com交流。 本文出自 "对影成三人" 博客,请务必保留此出处http://ticktick.blog.51cto.com/823160/1602611 "file:///sdcard/test.jpg" "content://media/external/images/media/21936"
Uri imageUri = Uri.fromFile(new File("/sdcard/test.jpg"));
public void pickImage() { Intent intent = new Intent(Intent.ACTION_PICK); intent.setType("image/*"); startActivityForResult(intent,REQUEST_CODE_PICK_IMAGE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != RESULT_OK) { return; } if( requestCode == REQUEST_CODE_PICK_IMAGE ) { Uri imageUri = data.getData(); //...... } }
Uri pictureURL = Uri.fromFile(new File("/sdcard/temp.jpg")); public void takenPicture() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT,pictureURL ); startActivityForResult(intent,REQUEST_CODE_TAKEN_PICTURE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != RESULT_OK) { return; } if( requestCode == REQUEST_CODE_TAKEN_PICTURE ) { Uri imageUri = pictureURL; //...... } }
public void test( Uri imageUri ) { Uri croppedUri = Uri.fromFile(new File("/sdcard/cropped.jpg")); startSystemCropImage(imageUri,croppedUri); } public void startSystemCropImage( Uri src, Uri dst ) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.putExtra("crop", "true"); // 设置剪裁图片的源/目的地址URL intent.setDataAndType(src,"image/*"); intent.putExtra(MediaStore.EXTRA_OUTPUT,dst); // 设置剪裁图片的宽高比 //intent.putExtra("aspectX", 2); //intent.putExtra("aspectY", 1); // 固定剪裁图片的宽高值 //intent.putExtra("outputX", 680); //intent.putExtra("outputY", 480); // 为了防止内存限制以及各个厂商返回的数据不统一,建议不要直接使用这个返回的数据,而是数据返回的URL intent.putExtra("return-data", false); startActivityForResult(intent, REQUEST_CODE_SYSTEM_CROPPER); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != RESULT_OK) { return; } if( requestCode == REQUEST_CODE_IMAGE_CROPPER ) { Uri croppedUri = data.getExtras().getParcelable(MediaStore.EXTRA_OUTPUT); InputStream in = null; try { in = getContentResolver().openInputStream(croppedUri); Bitmap b = BitmapFactory.decodeStream(in); mImageView.setImageBitmap(b); } catch (FileNotFoundException e) { e.printStackTrace(); } } super.onActivityResult(requestCode, resultCode, data); }
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
没有评论:
发表评论