- 初略的翻了一下《1984》,直觉的浑身冷汗。 1 day ago
- 其实更愿意坚持,有时候也是不得以。 @mujiang 1 day ago
- 淘宝第一台小型机上的核心库的即将下线,完成了其五年的历史使命。接下来会有越来越多小型机存储的下线,pc化,水平化,可扩展高可用的趋势,不可阻挡。 2 days ago
- 卓越的书,昨天就已经收到了。但是今天才收到卓越的邮件,说库房已经安排发货,预计明天可以送达,请您耐心等待、保持电话畅通并注意查收。这是什么系统啊,囧。 2 days ago
- 昨天在卓越下单买的几本书上午就送到了,不到24小时,效率不错。 3 days ago
CAP原理与最终一致性
CAP原理(CAP Theorem)
在足球比赛里,一个球员在一场比赛中进三个球,称之为帽子戏法(Hat-trick)。在分布式数据系统中,也有一个帽子原理(CAP Theorem),不过此帽子非彼帽子。CAP原理中,有三个要素:
- 一致性(Consistency)
- 可用性(Availability)
- 分区容忍性(Partition tolerance)
CAP原理指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。因此在进行分布式架构设计时,必须做出取舍。而对于分布式数据系统,分区容忍性是基本要求,否则就失去了价值。因此设计分布式数据系统,就是在一致性和可用性之间取一个平衡。对于大多数web应用,其实并不需要强一致性,因此牺牲一致性而换取高可用性,是目前多数分布式数据库产品的方向。
当然,牺牲一致性,并不是完全不管数据的一致性,否则数据是混乱的,那么系统可用性再高分布式再好也没有了价值。牺牲一致性,只是不再要求关系型数据库中的强一致性,而是只要系统能达到最终一致性即可,考虑到客户体验,这个最终一致的时间窗口,要尽可能的对用户透明,也就是需要保障“用户感知到的一致性”。通常是通过数据的多份异步复制来实现系统的高可用和数据的最终一致性的,“用户感知到的一致性”的时间窗口则取决于数据复制到一致状态的时间。
最终一致性(eventually consistent)
对于一致性,可以分为从客户端和服务端两个不同的视角。从客户端来看,一致性主要指的是多并发访问时更新过的数据如何获取的问题。从服务端来看,则是更新如何复制分布到整个系统,以保证数据最终一致。一致性是因为有并发读写才有的问题,因此在理解一致性的问题时,一定要注意结合考虑并发读写的场景。
从客户端角度,多进程并发访问时,更新过的数据在不同进程如何获取的不同策略,决定了不同的一致性。对于关系型数据库,要求更新过的数据能被后续的访问都能看到,这是强一致性。如果能容忍后续的部分或者全部访问不到,则是弱一致性。如果经过一段时间后要求能访问到更新后的数据,则是最终一致性。
最终一致性根据更新数据后各进程访问到数据的时间和方式的不同,又可以区分为:
- 因果一致性。如果进程A通知进程B它已更新了一个数据项,那么进程B的后续访问将返回更新后的值,且一次写入将保证取代前一次写入。与进程A无因果关系的进程C的访问遵守一般的最终一致性规则。
- “读己之所写(read-your-writes)”一致性。当进程A自己更新一个数据项之后,它总是访问到更新过的值,绝不会看到旧值。这是因果一致性模型的一个特例。
- 会话(Session)一致性。这是上一个模型的实用版本,它把访问存储系统的进程放到会话的上下文中。只要会话还存在,系统就保证“读己之所写”一致性。如果由于某些失败情形令会话终止,就要建立新的会话,而且系统的保证不会延续到新的会话。
- 单调(Monotonic)读一致性。如果进程已经看到过数据对象的某个值,那么任何后续访问都不会返回在那个值之前的值。
- 单调写一致性。系统保证来自同一个进程的写操作顺序执行。要是系统不能保证这种程度的一致性,就非常难以编程了。
上述最终一致性的不同方式可以进行组合,例如单调读一致性和读己之所写一致性就可以组合实现。并且从实践的角度来看,这两者的组合,读取自己更新的数据,和一旦读取到最新的版本不会再读取旧版本,对于此架构上的程序开发来说,会少很多额外的烦恼。
从服务端角度,如何尽快将更新后的数据分布到整个系统,降低达到最终一致性的时间窗口,是提高系统的可用度和用户体验非常重要的方面。对于分布式数据系统:
- N — 数据复制的份数
- W — 更新数据是需要保证写完成的节点数
- R — 读取数据的时候需要读取的节点数
如果W+R>N,写的节点和读的节点重叠,则是强一致性。例如对于典型的一主一备同步复制的关系型数据库,N=2,W=2,R=1,则不管读的是主库还是备库的数据,都是一致的。
如果W+R<=N,则是弱一致性。例如对于一主一备异步复制的关系型数据库,N=2,W=1,R=1,则如果读的是备库,就可能无法读取主库已经更新过的数据,所以是弱一致性。
对于分布式系统,为了保证高可用性,一般设置N>=3。不同的N,W,R组合,是在可用性和一致性之间取一个平衡,以适应不同的应用场景。
- 如果N=W,R=1,任何一个写节点失效,都会导致写失败,因此可用性会降低,但是由于数据分布的N个节点是同步写入的,因此可以保证强一致性。
- 如果N=R,W=1,只需要一个节点写入成功即可,写性能和可用性都比较高。但是读取其他节点的进程可能不能获取更新后的数据,因此是弱一致性。这种情况下,如果W<(N+1)/2,并且写入的节点不重叠的话,则会存在写冲突
参考文章:
[1].http://devblog.streamy.com/2009/08/24/cap-theorem/
[2].http://www.julianbrowne.com/article/viewer/brewers-cap-theorem
[3].http://www.allthingsdistributed.com/2008/12/eventually_consistent.html
[4].http://www.infoq.com/cn/news/2008/01/consistency-vs-availability
dstat:一款简单直观的os实时监控工具
在oschina上闲逛,发现一款不错的os实时监控工具dstat,整合了vmstat, iostat, ifstat, netstat等常见os监控工具的优点,输出的结果简单直观,并且结果可以保存到csv文件,这样再写一个简单的perl脚本,就能将os的主要监控信息一次性全部抓取出来,保存到监控数据库中用于分析展示。试用了一下觉得非常不错,因此在这里分享一下这个用python写的工具。
$dstat ----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system-- usr sys idl wai hiq siq| read writ| recv send| in out | int csw 2 0 98 0 0 0| 80k 54k| 0 0 | 335B 381B|1297 1301 22 2 74 0 0 2| 0 416k| 621k 219k| 0 0 |1158 26k 23 3 72 0 0 2| 64k 484k| 11k 11k| 0 0 |1109 30k 21 3 75 0 0 2|4096B 416k| 77k 77k| 0 0 |2104 25k 29 4 66 0 0 2| 0 1240k| 996k 425k| 0 0 |1350 28k
$dstat -ta --output osstat.csv -----time----- ----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system-- date/time |usr sys idl wai hiq siq| read writ| recv send| in out | int csw 05-02 11:37:08| 2 0 98 0 0 0| 80k 54k| 0 0 | 335B 381B|1297 1301 05-02 11:37:09| 16 4 78 0 0 3| 0 1404k|1478k 939k| 0 0 |4316 33k 05-02 11:37:10| 20 2 76 0 0 2| 0 1144k|1109k 828k| 0 0 |5653 28k 05-02 11:37:11| 13 2 83 0 0 2| 0 588k|2590k 1684k| 0 0 |4256 23k
$dstat -h
Usage: dstat [-afv] [options..] [delay [count]]
Versatile tool for generating system resource statistics
Dstat options:
-c, --cpu enable cpu stats
-C 0,3,total include cpu0, cpu3 and total
-d, --disk enable disk stats
-D total,hda include hda and total
-g, --page enable page stats
-i, --int enable interrupt stats
-I 5,eth2 include int5 and interrupt used by eth2
-l, --load enable load stats
-m, --mem enable memory stats
-n, --net enable network stats
-N eth1,total include eth1 and total
-p, --proc enable process stats
-s, --swap enable swap stats
-S swap1,total include swap1 and total
-t, --time enable time/date output
-T, --epoch enable time counter (seconds since epoch)
-y, --sys enable system stats
--ipc enable ipc stats
--lock enable lock stats
--raw enable raw stats
--tcp enable tcp stats
--udp enable udp stats
--unix enable unix stats
-M stat1,stat2 enable external stats
--mods stat1,stat2
-a, --all equals -cdngy (default)
-f, --full expand -C, -D, -I, -N and -S discovery lists
-v, --vmstat equals -pmgdsc -D total
--integer show integer values
--nocolor disable colors (implies --noupdate)
--noheaders disable repetitive headers
--noupdate disable intermediate updates
--output file write CSV output to file
delay is the delay in seconds between each update
count is the number of updates to display before exiting
The default delay is 1 and count is unspecified (unlimited)
PostgreSQL备份
PostgreSQL也支持逻辑备库和物理备份两种方式。物理备份可以和Oracle一样实现联机热备份,并且同样也需要将数据库设置为归档模式。
逻辑备份
PostgreSQL提供了pg_dump/pg_dumpall两个程序可以用来将数据dump成文本文件,实现数据的逻辑备份。使用不同的参数,可以将数据dump成PostgreSQL专用的数据格式(生成copy语句)或者标准SQL语句(生成insert语句)格式。恢复只需要简单的使用psql将文件执行一遍即可。另外也可以使用pg_restore工具来恢复数据。
利用pg_dump备份test数据库(只有一张test表),包括重建表的DDL语句,授权语句等所有信息,生成copy格式的文件:
$ ./pg_dump test
--
-- PostgreSQL database dump
--
SET statement_timeout = 0;
SET client_encoding = 'UTF8';
SET standard_conforming_strings = off;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET escape_string_warning = off;
SET search_path = public, pg_catalog;
SET default_tablespace = '';
SET default_with_oids = false;
--
-- Name: test; Type: TABLE; Schema: public; Owner: postgres; Tablespace:
--
CREATE TABLE test (
i integer
);
ALTER TABLE public.test OWNER TO postgres;
--
-- Data for Name: test; Type: TABLE DATA; Schema: public; Owner: postgres
--
COPY test (i) FROM stdin;
1
2
\.
--
-- Name: public; Type: ACL; Schema: -; Owner: postgres
--
REVOKE ALL ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON SCHEMA public FROM postgres;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO PUBLIC;
--
-- PostgreSQL database dump complete
--
利用pg_dump备份test库,只保存数据,insert语句格式:
[postgres@dbconsole bin]$ ./pg_dump --inserts -a test -- -- PostgreSQL database dump -- SET statement_timeout = 0; SET client_encoding = 'UTF8'; SET standard_conforming_strings = off; SET check_function_bodies = false; SET client_min_messages = warning; SET escape_string_warning = off; SET search_path = public, pg_catalog; -- -- Data for Name: test; Type: TABLE DATA; Schema: public; Owner: postgres -- INSERT INTO test VALUES (1); INSERT INTO test VALUES (2); -- -- PostgreSQL database dump complete --
物理备份
和Oracle一样,物理备份可以分为冷备份和热备份。冷备份就是将数据库实例关闭,然后直接复制data目录的所有文件,恢复时只需要将文件copy到data目录,无须利用日志(WAL–Write-Ahead Logging)进行恢复。而热备份,则需要利用日志将数据库恢复到一致状态,因此需要先将数据库置于归档模式。
PostgreSQL归档模式使用参数archive_mode控制,这是一个静态参数,修改postgresql.conf文件,加入如下参数,然后重启生效:
archive_mode = on archive_command = 'cp "%p" /u01/postgresql/arch/"%f"' archive_timeout = 600
postgres=# show archive_mode; archive_mode -------------- on (1 row)
由于postgresql没有归档进程,因此归档是通过外部命令(OS)完成的,archive_command用于指定该外部命令,具体格式请参考文档。如果是linux归档到本地,使用cp即可,如果是到远程,则可以使用scp或者rsync。archive_timeout强制N秒以后进行一次归档,这个和Oracle的archive_lag_target参数的作用一样。当然也可以手工进行日志切换:
postgres=# select pg_switch_xlog(); pg_switch_xlog ---------------- 0/7000000 (1 row)
热备份前,需要先将数据库置于备份状态,这一点和Oracle的手工也备份也是一样的。该命令会导致一次checkpoint,可能在业务高峰期会带来一些压力和风险,因此备份还是需要安排在业务低谷期间执行比较稳妥。
postgres=# select pg_start_backup('test_backup');
pg_start_backup
-----------------
0/8000020
(1 row)
然后在os层面将data目录进行复制备份。完成后,再取消备份状态,该命令同时会执行一次日志切换,并进行归档,以保证热备份期间的日志都已经归档,保证恢复数据库到一致状态的所有日志都能从归档中找到:
postgres=# select pg_stop_backup(); pg_stop_backup ---------------- 0/8000088 (1 row)
备份完成后,可以在归档目录找到一个记录了本次备份信息的文件:
$ more 000000010000000000000008.00000020.backup START WAL LOCATION: 0/8000020 (file 000000010000000000000008) STOP WAL LOCATION: 0/8000088 (file 000000010000000000000008) CHECKPOINT LOCATION: 0/8000020 START TIME: 2010-02-03 12:24:57 CST LABEL: test_backup STOP TIME: 2010-02-03 12:24:59 CST
PostgreSQL官方并没有提供和Oracle的rman一样的备份工具,不过因为PostgreSQL是开源的数据库,因此也有一个开源的工具pg_rman可以使用,从命令行来看功能已经非常强大,暂时还没有测试,有兴趣的可以研究一下。
pg_rman [ OPTIONS ] { init | backup | restore | show [ DATE | timeline ] |
validate [ DATE ] | delete DATE }
PostgreSQL安装
PostgreSQL8.x版本的安装已经非常的简单了。EnterpriseDB制作了一键安装的版本,包括FreeBSD/Linux/Mac OS X/Solaris/Windows平台都有。不过即使使用源码编译,也非常的简单。各个版本的源码可以点这里下载。
创建os用户
#useradd -g dba postgres #su - postgres
编译
$tar -zxvf postgresql-8.4.2.tar.gz $cd postgresql-8.4.2 $./configure --prefix=/OPT/postgresql --enable-profiling --with-blocksize=8 --with-wal-blocksize=8 $make && make install
其中with-blocksize指定数据块大小,默认8k,with-wal-blocksize指定日志块大小,默认也是8k。更多编译配置选项,可以通过./configure –help查看。
初始化database,注意PostgreSQL在服务端不支持GBK编码。
$cd /opt/postgresql/bin
$ ./initdb --encoding=utf8 -D /opt/postgresql/data
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.
The database cluster will be initialized with locale en_US.UTF-8.
The default text search configuration will be set to "english".
creating directory /opt/postgresql/data ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 32MB
creating configuration files ... ok
creating template1 database in /opt/postgresql/data/base/1 ... ok
initializing pg_authid ... ok
initializing dependencies ... ok
creating system views ... ok
loading system objects' descriptions ... ok
creating conversions ... ok
creating dictionaries ... ok
setting privileges on built-in objects ... ok
creating information schema ... ok
vacuuming database template1 ... ok
copying template1 to template0 ... ok
copying template1 to postgres ... ok
WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the -A option the
next time you run initdb.
Success. You can now start the database server using:
./postgres -D /opt/postgresql/data
or
./pg_ctl -D /opt/postgresql/data -l logfile start
初始化完成后,会在 /opt/postgresql/data目录生成数据库的文件,至此,软件安装完毕,数据库创建完毕。
启动数据库
./pg_ctl -D /opt/postgresql/data/ -l /opt/postgresql/log/alert.log start
启动后,可以发现PostgreSQL实例一共运行了5个进程
$ ps -ef | grep postgres postgres 17572 1 0 16:41 pts/2 00:00:00 /opt/postgresql/bin/postgres -D /opt/postgresql/data postgres 17574 17572 0 16:41 ? 00:00:00 postgres: writer process postgres 17575 17572 0 16:41 ? 00:00:00 postgres: wal writer process postgres 17576 17572 0 16:41 ? 00:00:00 postgres: autovacuum launcher process postgres 17577 17572 0 16:41 ? 00:00:00 postgres: stats collector process postgres 18679 20791 0 16:47 pts/2 00:00:00 grep postgres
其中wal writer process是日志写进程。
常用标签: oracle life MySQL Oracle11g blog dba 新特性 oow2009 oow linux
最新评论 | Recent comments
- guanghui: 我很早就开始关注zfs,然后自然也关...
- thomas zhang: 这个bug是够恶心的 官方11.2.0.2 Release...
- 巫师勋: 这里面有一些理念和ASM很像啊,确实...
- 大头刚: EXT4 对内核的要求太高,大规模的迁...
- ruochen: ext4的稳定性现在应该说已经很不错了...
- Rain@DNA: 是的,目前的一些主流版本里已经集...
- icavy: 这里探讨 404错...
- 驾照: 哥们挺厉害的。我练了好久,倒桩和...
- icavy: 现在不用穿墙也可以...
- NinGoo: @supsyg 这个应该是tnsname本身有问题吧...
- supsyg: 试了一下,速度还不错,但tns连接好...
- 再现9527: 多开开就好,现在的驾校培养出来很...
- 曾经的阿飞: sysbench可以使用oltp-table-size指定自动...
- 曾经的阿飞: 你说concurrency参数是不是和sysbench的num...
- ppg: 有车之人,羡慕啊,正努力赚钱中.....
