#######################################################################
数据存储的趋势和大数据带来的挑战
分布式存储与CAP定理
分布式存储文件系统
Mogilefs基本原理
Mogilefs实现
Nginx反向代理Tracker节点
当下我们处在一个互联网飞速发展的信息社会,在海量并发连接的驱动下每天所产生的数据量必然以几何方式增长,随着信息连接方式日益多样化,数据存储的结构也随着发生了变化。在这样的压力下使得人们不得不重新审视大量数据的存储所带来的挑战,例如:数据采集、数据存储、数据搜索、数据共享、数据传输、数据分析、数据可视化等一系列问题。
传统存储在面对海量数据存储表现出的力不从心已经是不争的事实,例如:纵向扩展受阵列空间限制、横向扩展受交换设备限制、节点受文件系统限制。
然而分布式存储的出现在一定程度上有效的缓解了这一问题,之所以称之为缓解是因为分布式存储在面对海量数据存储时也并非十全十美毫无压力,依然存在的难点与挑战例如:节点间通信、数据存储、数据空间平衡、容错、文件系统支持等一系列问题仍处在不断摸索和完善中。
首先要说明的是一个完美分布式系统有三个最重要的元素,他们分别是:
一致性(Consistency):任何一个读操作总是能读取之前完成的写操作。
可用性(Availability):每次操作总是能够在预定时间返回。
分区容错性(Partition Tolerance):在出现网络分区(分布式)的情况下,仍然能够满足一致性和可用性。
<a target="_blank" href="http://blog.51cto.com/attachment/201312/032623364.png"></a>
2007年,正当所有科学家都在致力于CAP三元素并存的时候,Eric.Brewer教授站了出来并指出CAP永远无法兼顾,只能根据具体应用来权衡和取舍,并且至多两个元素可以共存,后来由两位麻省理工学院的科学家证明此观点是具有前瞻性的,由此形成Brewer的CAP定理。
正所谓鱼和熊掌不可兼得,关注一致性就需要处理因系统不可用而带来写操作失败的情况,反之关注可用性就无法保证每次都能读取到最新的写入操作。传统关系型数据库侧重于CA,而非关系型键值数据库则侧重于AP。
对于大型站点,可用性(Availability)与分区容错性(Partition Tolerance)的优先级会高于一致性(Consistency),这里并不是指完全舍弃一致性,而是通过其他手段实现数据的弱一致性,例如:用户微博的浏览数和评论可以容忍相对长时间的不一致,几乎不会影响用户体验,而股票价格的数据则异常敏感,即便是10秒钟的数据不一致也无法容忍,为了能更形象的了解所谓“各种一致性”需要进行一下内容的回顾。
强一致性(ACID):在单机环境中,强一致性可以由数据库的事务来保证;在分布式环境中,强一致性很难做到,即便是做到也会因为分布式事物所带来的性能低下,不适合在互联网的环境中应用。
弱一致性(包括最终一致性):系统不能保证后续访问返回最新的值,在访问到最新值之前这段时间称之为不一致窗口。
最终一致性:是弱一致性的一种特例,存储系统保证如果对象有多次更新,在渡过不一致窗口之后必将放回最后更新的值。
服务器的一致性:N代表节点的个数;W代表更新的时候需要确认已经被更新的节点个数;R代表读取数据需要的节点数量。
W + R > N ----> 强一致性(通常N=3,W=R=2)
W=N,R=1 ----> 最佳读
W=1,R=N ----> 最佳写
W + R <= N ----> 弱一致性
Google Filesystem
GFS+MapReduce擅长处理单个大文件
Hadoop Distributed Filesystem
GFS的山寨版+MapReduce,擅长处理单个大文件
ClusterFS
擅长处理单个大文件
Taobao Filesystem
擅长处理海量小文件
MogileFS
Ceph
是一个 Linux PB级别的分布式文件系统
MooseFS
通用简便,适用于研发能力不强的公司
Lustre
一种平行分布式文件系统
MogileFS是一个开源的分布式文件系统,用于组建分布式文件集群,由LiveJournal旗下DangaInteractive公司开发,Danga团队开发了包括 Memcached、MogileFS、Perlbal等不错的开源项目:(注:Perlbal是一个强大的Perl写的反向代理服务器)。MogileFS是一个开源的分布式文件系统。主要特性包括:应用层的组件、无单点故障、自动文件复制、具有比RAID更好的可靠性、无需RAID支持等……核心角色如下:
tracker节点:借助数据库保存各节点文件的元数据信息保存每个域中所有键的存储位置分布,方便检索定位数据位置的同时监控各节点,告诉客户端存储区位置并指挥storage节点复制数据副本,进程名为mogilefsd(7001)。
database节点:为tracker节点提供数据存取服务。
storage节点:将指定域中的键转换为其特有的文件名存储在指定的设备文件中,转换后的文件名为值,storage节点自动维护键值的对应关系,storage节点由于使用http进行数据传输,因此依赖于perlbal,storage节点前端可以使用nginx进行反向代理,但需要安装nginx-mogilefs-module-master模块进行名称转换,进程名mogstored(7501),perbal(7500)。
Domain:一个域中的键值是惟一的,一个MogileFS可以有多个域,域可以用来存储不同应用类型的数据的容器。
Host:每一个存储节点称为一个主机,一个主机上可以有多个存储设备(单独的硬盘),每个设备都有ID号,Domain+Fid用来定位文件。
Class:复制最小单位,文件属性管理,定义文件存储在不同设备上份数。
流程图如下:
1、应用层发起GET请求到Nginx。
2、Nginx根据负载均衡机制随机代理到后台Node one。
3、Node one向从服务器发起查询请求。
4、从服务器返回查询结果。
5、Node one将查询结果返回给Nginx。
6、Nginx将查询结果根据模块转换为合理的url方位Node three。
7、Node Three将文件内容通过http协议返回给Nginx。
8、Nginx将结果返回给应用层的请求。
由于各角色和服务之间都是基于套接字通信,就服务本身来说没有耦合性,所以可以使用少量机器运行多种服务角色,功能图如下:
<a target="_blank" href="http://blog.51cto.com/attachment/201312/034037457.png"></a>
1、通过Nginx+Keepalived实现高可用的负载均衡,通过upstream模块可以有选择性的转发应用层的请求至后端tracker节点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<code>##### Database节点</code>
<code>安装mariadb</code>
<code>授权</code>
<code>GRANT ALL ON *.* TO </code><code>'root'</code><code>@</code><code>'%'</code> <code>IDENTIFIED BY </code><code>'mypass'</code><code>;</code>
<code>CREATE DATABASE mogilefs;</code>
<code>GRANT ALL ON mogilefs.* TO </code><code>'moguser'</code><code>@</code><code>'%'</code> <code>IDENTIFIED BY </code><code>'mogpass'</code><code>;</code>
<code>FLUSH PRIVILEGES;</code>
<code>##### Tracker节点(可以是所有节点)</code>
<code>安装 mogilefs</code>
<code>修改配置文件如下</code>
<code>vim </code><code>/etc/mogilefs/mogilefsd</code><code>.conf </code>
<code>daemonize = 1</code>
<code>pidfile = </code><code>/var/run/mogilefsd/mogilefsd</code><code>.pid</code>
<code>db_dsn = DBI:mysql:mogilefs:host=192.168.1.241</code>
<code>db_user = moguser</code>
<code>db_pass = mogpass</code>
<code>listen = 0.0.0.0:7001</code>
<code>conf_port = 7001</code>
<code>query_jobs = 100</code>
<code>delete_jobs = 1</code>
<code>replicate_jobs = 5</code>
<code>reaper_jobs = 1</code>
<code>service mogilefsd start </code><code>#启动服务</code>
<code>ss -tanlp (LISTEN 0 128 192.168.1.241:7001 )</code>
<code>##### storage节点(可以是所有节点)</code>
<code>mkdir</code> <code>/mogdata/dev1</code> <code>-pv </code><code>#创建设备目录</code>
<code>chown</code> <code>-R mogilefs.mogilefs </code><code>/mogdata/dev2/</code> <code>#权限</code>
<code>vim </code><code>/etc/mogilefs/mogstored</code><code>.conf</code>
<code>maxconns = 10000</code>
<code>httplisten = 0.0.0.0:7500</code>
<code>mgmtlisten = 0.0.0.0:7501</code>
<code>docroot = </code><code>/mogdata</code> <code>#目录级别</code>
<code>service mogstored start</code>
<code>ss -tanlp (*:7500)</code>
<code>##### tracker节点添加storage节点和常用命令</code>
<code>mogadm check </code><code>#检测节点</code>
<code>mogadm host list </code><code>#每个存储节点称为一个host</code>
<code>mogadm host add 192.168.1.213 --ip=192.168.1.213 --ip=192.168.1.213 --status=alive </code><code>#添加第一个存储节点</code>
<code>mogadm host add 192.168.1.242 --ip=192.168.1.242 --ip=192.168.1.242 --status=alive </code><code>#添加第一个存储节点</code>
<code>mogadm host add 192.168.1.241 --ip=192.168.1.241 --ip=192.168.1.241 --status=alive </code><code>#添加第一个存储节点</code>
<code>mogadm device add 192.168.1.213 1 </code><code>#添加第一个设备,设备号唯一不能重名</code>
<code>mogadm device add 192.168.1.242 2 </code><code>#添加第二个设备</code>
<code>mogadm device add 192.168.1.241 3 </code><code>#添加第三个设备</code>
<code>mogadm check </code><code>#可以查看状态</code>
<code>mogadm domain add files </code><code>#创建文件存储域</code>
<code>mogadm domain add images </code><code>#创建图片存储域</code>
<code>mogadm domain list </code><code>#查看所有域</code>
<code>mogupload --trackers=192.168.1.241 --domain=files --key=</code><code>'/fstab'</code> <code>--</code><code>file</code><code>=</code><code>'/etc/fstab'</code> <code>#上传fstab文件,key为'/fstab'</code>
<code>mogfileinfo --trackers=192.168.1.241 --domain=files --key=</code><code>'/fstab'</code> <code>#根据key查看文件存放信息</code>
注释:mogupload工具是为了测试,实际环境中上传是由程序员在代码中使用mogilefs的API进行交互。
<a target="_blank" href="http://blog.51cto.com/attachment/201312/042651555.png"></a>
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<code>##### 配置Nginx</code>
<code>安装tng</code>
<code>yum </code><code>install</code> <code>pcre-devel -y</code>
<code>yum groupinstall </code><code>"Development Tools"</code> <code>"Server Platform Development"</code>
<code>yum </code><code>install</code> <code>libxslt-devel gd-devel lua-devel geoip-devel</code>
<code>tengine-1.5.1.</code><code>tar</code><code>.gz</code>
<code>nginx-mogilefs-module-master.zip </code><code>#mogilefs模块需要打补丁</code>
<code>mkdir</code> <code>-pv </code><code>/var/tmp/nginx/client</code> <code>#模块需要</code>
<code>unzip nginx-mogilefs-module-master.zip</code>
<code>useradd</code> <code>-r nginx</code>
<code>.</code><code>/configure</code> <code>\</code>
<code> </code><code>--prefix=</code><code>/usr/local/nginx</code> <code>\</code>
<code> </code><code>--sbin-path=</code><code>/usr/local/nginx/sbin/nginx</code> <code>\</code>
<code> </code><code>--conf-path=</code><code>/etc/nginx/nginx</code><code>.conf \</code>
<code> </code><code>--error-log-path=</code><code>/var/log/nginx/error</code><code>.log \</code>
<code> </code><code>--http-log-path=</code><code>/var/log/nginx/access</code><code>.log \</code>
<code> </code><code>--pid-path=</code><code>/var/run/nginx/nginx</code><code>.pid \</code>
<code> </code><code>--lock-path=</code><code>/var/lock/nginx</code><code>.lock \</code>
<code> </code><code>--user=nginx \</code>
<code> </code><code>--group=nginx \</code>
<code> </code><code>--</code><code>enable</code><code>-mods-shared=all \</code>
<code> </code><code>--add-module=</code><code>/nginx-mogilefs-module-master</code>
<code>make</code> <code>&& </code><code>make</code> <code>install</code>
<code>vim </code><code>/etc/profile</code><code>.d</code><code>/nginx</code><code>.sh</code>
<code>export</code> <code>PATH=</code><code>/usr/local/nginx/sbin</code><code>:$PATH</code>
<code>. !$</code>
<code>提供脚本.....</code>
<code>配置nginx</code>
<code>vim </code><code>/etc/nginx/nginx</code><code>.cfg</code>
<code>upstream trackers {</code>
<code> </code><code>server 192.168.1.242:7001 weight=1;</code>
<code> </code><code>server 192.168.1.213:7001 weight=1;</code>
<code> </code><code>server 192.168.1.241:7001 backup;</code>
<code> </code><code>check interval=3000 rise=2 fall=5 timeout=1000;</code>
<code> </code><code>check_http_send </code><code>"GET / HTTP/1.0\r\n\r\n"</code><code>;</code>
<code> </code><code>check_http_expect_alive http_2xx http_3xx;</code>
<code> </code><code>}</code>
<code>location </code><code>/jpg/</code> <code>{</code>
<code> </code><code>mogilefs_tracker trackers;</code>
<code> </code><code>mogilefs_domain images;</code>
<code> </code><code>mogilefs_methods GET;</code>
<code> </code><code>mogilefs_pass {</code>
<code> </code><code>proxy_pass $mogilefs_path;</code>
<code> </code><code>proxy_hide_header Content-Type;</code>
<code> </code><code>proxy_buffering off;</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
<code>##### 配置keepalived</code>
<code>安装keepalived</code>
<code>vim </code><code>/etc/keepalived/keepalived</code><code>.conf </code><code># backup priority 99</code>
<code>global_defs {</code>
<code> </code><code>notification_email {</code>
<code> </code><code>root@localhost</code>
<code> </code><code>notification_email_from admin@localhost</code>
<code> </code><code>smtp_server 127.0.0.1</code>
<code> </code><code>smtp_connect_timeout 30</code>
<code> </code><code>router_id LTT</code>
<code>}</code>
<code>vrrp_script chk_nginx {</code>
<code> </code><code>script </code><code>"killall -0 nginx"</code>
<code> </code><code>interval 1</code>
<code> </code><code>weight -2</code>
<code> </code><code>fall 2</code>
<code> </code><code>rise 1</code>
<code>vrrp_instance IN_1 {</code>
<code> </code><code>state MASTER</code>
<code> </code><code>interface eth0</code>
<code> </code><code>virtual_router_id 22</code>
<code> </code><code>priority 100</code>
<code> </code><code>advert_int 1</code>
<code> </code><code>authentication {</code>
<code> </code><code>auth_type PASS</code>
<code> </code><code>auth_pass aaaa</code>
<code> </code><code>}</code>
<code> </code><code>virtual_ipaddress {</code>
<code> </code><code>192.168.1.222</code>
<code> </code><code>track_script {</code>
<code> </code><code>chk_nginx</code>
查看负载节点:
<a target="_blank" href="http://blog.51cto.com/attachment/201312/045554770.png"></a>
模拟GET方法测试Nginx_mogilefs模块:
<a target="_blank" href="http://blog.51cto.com/attachment/201312/045933806.png"></a>
本文转自 ftmoonfans 51CTO博客,原文链接:http://blog.51cto.com/soulboy/1338192