闲谈MongoDb+GridFS+Nginx

简介:
原文:
http://tech.techweb.com.cn/thread-433779-1-1.html
http://nightsailer.com/2009/11/13/499.html

MongoDb果然是个好东西. 我在最近的一个项目实践中, 实验性的用到了这个东西.
在测试中,对于GridFS相当满意. 首先, 和传统的MogileFS不同, gridfs可以和其它的meta 数据 部署在同一个
db中,默认的会为gridfs的collection分别创建fs.files和fs.chunks. 5 W. p" X  o9 x7 t" a. O% X
当存储一个 文件 时,可以附加存入任意的附加信息,因为这些信息实际上也是一个普通的collection.
这个特性给我们省了好多的事情. 以前,如果要存储一个附件,通常的做法是,在主 数据库 中存放文件的属性,并且记录
文件的path.当查询某个文件时,需要首先查询数据库,获得path,然后从存储 系统 中获得相应的文件. 4 F/ R5 M& [6 U" N
在使用gridfs时,则非常简单, 我们可以直接将这些信息直接存储到文件中. 比如下面的 PHP 代码 ,存储上传的文件到gridfs: 8 g8 T& a# `* L3 B6 ~. x& a, ^
. ]% d) X" P' ~6 L5 {9 u
public function store($file,$attrs=array()) {
if (!is_file($file)) { / G& e, A1 I, B- J7 k
throw new CZone_Core_Service_Exception("File:$file not exists"); ) }' E, f( x# U: ^
}
$defaults = array( * F. g# h5 h" j( e0 Q
'content_type'=> null, * Q& t' u/ D1 |, @' U
'art_id'=>-1, % q1 R, V- V2 h$ x
'state' => self::STORE_STATE_TMP, ( o& _9 w9 X2 i) B/ ^( ?
'created_on' => time(), 6 f- K: i) |" P- x9 @6 z- N2 U
'is_thumb'=>  false ,
'md5'=> md5_file($file) , a! I$ |& Z3 O/ Z* S2 Y7 H
);
$asset_attrs = $attrs+$defaults; & \) s; a& N! P' I" B
if (!isset($asset_attrs['content_type'])) { 3 O9 ^6 O1 o3 Z1 N% h) r# z  X
$asset_attrs['content_type'] = Doggy_Util_File::mime_content_type($file); , k( E% g2 `  h
}
$fs = $this->db->get_fs(); ; Z% x0 z! G8 U8 i
return $fs->storeFile($file,$asset_attrs); : v& O- N  w, x& w. p2 h0 H
}

调用store时,可以附件任意属性数组. 之后, 检索文件时则可以根据这些属性来查找:
3 J% K3 m* i8 \; a5 e) m5 J6 X
public function fetch_by_id($id) {
return $this->fetch(array('_id'=>$id));
} # p0 J+ k9 Y, D" Z$ c5 h" c
public function delete_by_id($id) { 3 M. \* ]& t% B
return $this->delete(array('_id'=>$id)); - f5 k% Z" ]4 H  t( }. u  T* u3 Z
}
public function delete_art_assets($art_id) { / X4 |: q6 h$ @4 l/ C! W
return $this->delete(array('art_id'=>$art_id)); % C7 ]5 r/ m+ b# c# y* k: {
}
public function delete_asset($asset_id) {
return $this->delete_by_id($asset_id) && $this->delete_asset_thumbs($asset_id);
}
public function delete($options) {
if (isset($options['_id'])) {
$options['_id'] = Doggy_Mongo_Db::id($options['_id']); 5 M2 M! H( M, K. N( D8 B
}
$fs = $this->db->get_fs(); % H! B2 h" M9 f
return $fs->remove($options); 9 J+ K7 R8 N0 k/ b1 i) o; J4 n' t
} : Z7 R4 L$ e' @) s: {6 {& z
public function find_all($query=array(),$fields=array()) {
return $this->db->fs_find($query,$fields);
}

使用gridfs,可以把原先复杂的操作变得相当简单, 真正实现了mogodb设计者的想法, . m5 x& i6 n5 J: i# E+ a, h: N0 |
数据库为什么不能做文件系统?
在实践中,我发现GridFS和之前研究的MogileFS一些基本方式其实是相通的. 只不过, mogilefs的存储节点是 3 ]) W. o1 w/ L* r
使用了简化版本的DAV 而已.
从这个角度,完全可以设计一个基于mongo gridfs的mogilefs.
至于性能, 从我的体会来说, 还不错. 毕竟我的项目的目前看存储仅限于TB级别.
不过在生产环境中,国外有用于存储视频流的. 
GridFS的一个优点是可以存储上百万的文件而无需担心扩容性. 0 `  O" E! O/ ~( w) E. Y* M
通过同步复制,可以 解决 分布式文件的备份问题.
目前,mongo支持主-从和Replica Pairs以及受限的Master-Master Replication. 2 q4 _$ C1 D/ q0 m
比较实用的还是前2种. / }. q6 ?: m7 _
通过ARP-ping可以实现一个双机热备切换,类似我正在用的my sql 的mmm.
在实验过后,感觉使用mongo是非常轻松. 很轻松就解决了高并发中经常会遇到的问题,
比如实时的日志处理,实时的统计,更新某个字段.
通过使用mongo的capped collection,可以实现cache, message queue等特性,无需附加成本.
还有share session.
部署 . z# Q6 \& C# v
gridfs的部署的选择 方案 不多,大概有以下几种:   V; E; D- q3 T  D
1. 通过mongo client 的script, 比如PHP.
优点是简单,缺点是每次都要读取mongo数据库. 虽然mongo的性能不错,但是似乎总是不忍.   [, H+ a( \" c! ?
另外,像PHP的DRIVER并不支持HTTP RANGE header,这样就无法支持断点续传. ) h+ w7 c3 k5 |9 c5 {' l
2.使用Nginx module & S- W$ S4 f1 z* k
http://github.com/mdirolf/nginx-gridfs
这是gridfs的nginx module. 可以通过nginx直接访问读取mongo gridfs中的文件.
和nginx对应的mogilefs module类似.
优点: 由于直接通过nginx,速度是最快的.
缺点: 只能通过file_path来查找,目前不支持_id来查找.因此必须在file_path上建立索引.
优化方案: 5 O! F( p5 i9 w5 E; D. b$ z7 ]
我自己构想了以下的优化方案: * Q6 R" O( v' K. E! {+ ^0 G& t
1. squid/varnish+script-backend 5 ~0 o6 s* C! J$ C2 K- X
在nginx前端加上一个squid或者varnish作为反向加速. 如果没有则通过 PHP脚本来获取.
应用 场景: 特别适合读取频繁的文件,比如用户的头像,热门图片,缩略图等. 不适合大文件.
缺点: 文件的过期必须正确设置. 此外配置好varnish或者squid
2. 基于proxy_store或fastcgi-cache, try_files
这种方案的应用场景同1, 但都是使用nginx的相应模块即可实现.
通过对fastcgi/proxy进行cache或store,就可以实现文件按需存储.
当使用proxy_store时,当后端文件变动时,需要purge这些文件.实现起来不难.
对于大文件,我觉得性价比比较高的一个方案是: 6 a, u/ |; L, l6 g0 J
使用Perl或者PHP写一个脚本作为fastcgi运行. 前端用nginx进行负载均衡. 7 ?6 q. I7 u, N, O" c
如果使用Pelr则当前driver支持随机读取,支持断点续传. 用PHP则需要做个简单处理,
手动判断HEADER,并计算出offset,然后再读取相应的字节流. + q7 `, D  y3 V3 l% M
注意,如果是用PHP,则最好的方案是单独编译一个PHP,仅保留”最基本”的特性.
这样,可以节省很多的资源占用,稳定性和速度也比较好.我建议的保留的特性有: ) y; S) V5 B2 X" b( W* w% o: M) p
json+mongo+spl. 7 h9 e7 }: @8 c2 x, j
PHP driver要比Perl更为成熟,虽然二者核心 开发 者都是一个人. Perl目前还是beta,也没有特别 + Y' E: k9 X* r5 N" Q+ {) I. H" b) z/ r
广泛的使用,但据说由于大部分使用的是PHP的C代码,所以还是非常可靠的.
其他一些信息: " Y  [4 s+ j/ P4 c6 Y
1.通过runcommand可以直接在mongodb端运行处理脚本. 比如像mapreduce,或者一些需要读取数据然后进行处理的. & ]& U* y7 j- A
这些command则是使用javascript方式来编写的,很容易. 好处就是避免了数据在 服务 端和客户端之间的读取和传输,
提高效率.
2. sharding
sharding在目前开发版中已经具备,但还不成熟. 但是可以自己实现sharding比较好.因为目前的sharding还是比较硬性的.
3.灵活使用magic操作符和upsert,比如$inc,$all,$in 等等
这些轻松解决一些麻烦的操作.
3.其他的复制方案 * j) X$ x1 r# z$ {3 J
对于文件系统, 其实可以通过一个脚本来定期将文件复制到其他的节点. 实现类似mogilefs的 功能 .
我对此比较有兴趣.
相关文章
|
网络协议 API
端口复用(bind error: Address already in use 问题)
端口复用(bind error: Address already in use 问题)
1514 0
|
7月前
|
传感器 人工智能 安全
物联网
万物互联,智启未来。物联网通过连接人、物、环境,重塑生活、城市与产业。从智能家居到智慧城市,从工业互联网到精准农业,数据驱动智能化变革。融合AI、5G等技术,构建高效、安全、可持续的智能世界,开启人类社会新篇章。(238字)
|
机器学习/深度学习 API TensorFlow
深入解析TensorFlow 2.x中的Keras API:快速搭建深度学习模型的实战指南
【8月更文挑战第31天】本文通过搭建手写数字识别模型的实例,详细介绍了如何利用TensorFlow 2.x中的Keras API简化深度学习模型构建流程。从环境搭建到数据准备,再到模型训练与评估,展示了Keras API的强大功能与易用性,适合初学者快速上手。通过简单的代码,即可完成卷积神经网络的构建与训练,显著降低了深度学习的技术门槛。无论是新手还是专业人士,都能从中受益,高效实现模型开发。
470 1
|
监控 安全 网络协议
计算机端口:网络通信的桥梁
计算机端口是网络通信的逻辑通道,支持数据传输和服务识别。本文介绍端口定义、分类(知名、注册、动态端口)、作用及管理方法,涵盖常用知名端口如HTTP(80)、HTTPS(443)等,并强调端口安全配置的重要性,帮助读者全面理解这一关键组件。
1365 6
|
缓存 资源调度 安全
深入探索Linux操作系统的心脏——内核配置与优化####
本文作为一篇技术性深度解析文章,旨在引领读者踏上一场揭秘Linux内核配置与优化的奇妙之旅。不同于传统的摘要概述,本文将以实战为导向,直接跳入核心内容,探讨如何通过精细调整内核参数来提升系统性能、增强安全性及实现资源高效利用。从基础概念到高级技巧,逐步揭示那些隐藏在命令行背后的强大功能,为系统管理员和高级用户打开一扇通往极致性能与定制化体验的大门。 --- ###
395 9
|
JavaScript 前端开发
利用 AST 进行代码优化
【10月更文挑战第25天】利用AST进行代码优化需要对编程语言的语法和语义有深入的理解,以及对AST的结构和遍历操作有熟练的掌握。通过合理地运用各种优化技术,可以显著提高代码的质量和性能。在实际应用中,通常会结合多种优化方法,并根据具体的项目需求和代码特点进行综合优化。
|
自然语言处理
如何使用ChatGPT写好简历?如何使用ChatGPT优化简历?21个写简历的ChatGPT的Prompts!
本文提供了一份详细的指南,教导求职者如何根据不同的工作描述和自身经验,创建和优化简历,包括专业摘要、技能强调、成就描述以及如何使简历内容更加突出和有针对性。
467 0
如何使用ChatGPT写好简历?如何使用ChatGPT优化简历?21个写简历的ChatGPT的Prompts!
|
安全 Unix Linux
【ARM】在NUC977上搭建基于boa的嵌入式web服务器
【ARM】在NUC977上搭建基于boa的嵌入式web服务器
647 0
|
网络协议 网络性能优化
基于 Wireshark 分析 TCP 协议
基于 Wireshark 分析 TCP 协议