杭州QCon总结–NoSQL
本文已发表在:http://www.5ilei.com/writing/2011-hangzhou-qcon-nosql.html
有幸参加了今年InfoQ在杭州首次举办的QCon大会,下面将我了解到的一些知识总结并分享给大家,其中有些是会后查资料了解的,有不正确的地方欢迎指出;
QCon中有一个专题专门介绍大数据及NoSQL,正好也对这方面有一点兴趣;介绍NoSQL的还真是多啊,Sina Weibo介绍Redis,盛大介绍MongoDB,Qunar介绍NoSQL常见误区及陷阱;
不管是哪种NoSQL产品,它们关注的点主要在以下几个方面:
1、schema-free
即模式自由;相比Oracle、MySQL等RDBMS数据库,NoSQL没有固定的schema;比如在MongoDB中,如果业务场景需要,完全可以把不同类型的文档(json串)存储在同一数据库中;Redis中则是针对存储的对象提供了更多的数据结构,如string, hash, list, set, sorted set等;
2、高性能访问
高并发下的读写请求,RDBMS的磁盘IO很难承受;而NoSQL则是将数据存放在内存中,读写操作全部在内存中完成;像Redis能达到(100k+set/80k+get)/s;
3、持久化
目前NoSQL持久化方案还不太成熟,主要方案是定时快照和日志两种方式;如
1) Redis:
- rdb:定时fork子进程来flush到磁盘,但是会影响主进程的服务响应;另外会丢失当前和上次flush之间的数据;
- aof:类似MySQL的binlog,对所有的写操作都会记录;影响主进程的写请求,同时aof数据较大,宕机后恢复很慢;
2) MongoDB:
- 定时备份:提供mongoexport/mongoimport,mongodump/mongorestore命令,但同样会丢失距上次备份的数据;
- oplog:写操作日志;当Master有写操作时,会在oplog中进行记录,Slave会根据oplog来达到数据同步;当oplog超过预设大小时,会覆盖老的记录,oplog大小至少要大于Slave同步oplog间隔所产生的日志文件大小;
4、备份与扩容:
1) Redis:
- Master/Slave同步:Slave在启动时会向Master发送sync命令并阻塞等待Master返回其内存快照文件,然后清空内存表,根据收到的内存快照文件重建内存数据结构;如果在同步过程中,Master有新的写操作,则会待内存快照发送完后再依次发给Slave,Slave再完成同步;之后如果Master有写请求会同步到Slave列表,从而保证数据一致性;
- 这种方式在在缺陷:Slave初始化时,导致Master需要做内存快照而带来压力;同时Slave需要时间来重建数据结构,要消耗一定时间,尤其是当线上Slave宕机后恢复,由于并非是增量复制,因此恢复速度是不能容忍的;
- 几种思路:
a.主动复制:避开Master/Slave同步,采用双写或多写;但由于双写或多写从而会带来数据一致性及性能上的问题;如果对数据一致性要求不高,可以采用这种方式,一旦一组集群挂掉,可以马上切换到另一组集群上;
b.增量复制:Redis目前的rdb快照和aof日志没有形成关联,因此不能做增量复制;如果Master在定时备份时,将内存快照和aof文件位置一起flush到磁盘,当Slave来同步时,Master可以将最新快照文件和aof发给Slave,Slave再根据aof位置和Master同步快照之后的更新,通过这种增量复制来避免Slave初始化时给Master带来压力;
c.MySQL+Redis实现读写分离:MySQL作为主库,Redis集群作为读请求高速缓存,所有写操作都基于MySQL,通过binlog实现Redis集群的同步;
a.Master/Slave集群中,应事先配置好所有从库,避免增加从库给主库带来压力;最好选择在低峰期进行;
b. 用Master/Slave实现读写分离,不适用于写密集型的场景,这样会对Master造成压力;2) MongoDB:
MongoDB有两种备份机制,Master/Slave和ReplicaSets,它们都是基于oplog来实现的;
Master/Slave:这种机制下,只有Master产生oplog,Slave会定时从Master同步实现备份同步;前面提到过oplog有大小限制;ReplicaSets:这种机制下,所有的服务器都会产生oplog,但任何时间只有一台机器会被选举成Master;当Master宕掉后,Slaves会重新选举新的Master,然后再与新的Master同步;自动分片:与数据库的分表类似,自动分片就是将数据集合依据一定的规则切分成若干小块,这些小块统一由mongos路由管理,当有请求查询或写入时,路由会依据分片shardkey规则找到对应的分片从而进行操作;分片解决了写密集操作,用于分散单一写服务器负载;同时如果原先的存储空间不够了,这个时候可能通过分片操作将之后的数据写入其它存储空间上;同样,可以采用Master/Slave或ReplicaSets来分片集群和路由服务器集群,但服务器资源比较浪费;
使用NoSQL的一些小tips
- 使用批量调用代替循环调用:循环调用相比批量调用,耗时更多;在外部完成数据压缩:都可以减小存储,但外部压缩可以提升网络IO性能;注意跨语言客户端的支持:是否能满足多语言客户端的需求,如序列化/反序列化、压缩/解压等;合适的场景选择合适的技术:CacheVSStore,MySQL+NoSQL(Cache);注意缓存重建引发数据库穿透;读请求同时到DB,对DB造成压力导致不可用;