Chinaunix

标题: 怎么解决NOSQL数据库数据持久性问题 [打印本页]

作者: 无风之谷    时间: 2012-01-10 16:13
标题: 怎么解决NOSQL数据库数据持久性问题
      目前的NOSQL主要分为两种,一种是基于内存型的如redis、memcached,一种是基于磁盘型的如Tokyo Tyrant、Tokyo Cabinet、Berkeley DB。
      redis、memcached这类内存型NOSQL。虽然读写效率很高,但是有一个大问题,就是数据库持久性。memcached是一重启进程数据就没了。redis支持两种持久化方式,一种是 Snapshotting(快照)也是默认方式,另一种是Append-only file(缩写aof)的方式。但是这两种效率都不高。 怎样才能做到高效读写,又能保持数据持久性了?
     
     以下这个解决方案是由CU热心网友“七夜”带来的:
     quickdb 是一款基于内存文件系统的 HashTable数据结构的Key-Value数据引擎. . 什么是内存文件系统了?就是操作系统把系统内存划出一部分当作硬盘使用。你可以像操作磁盘那样的操作内存。但效率远远比硬盘来的快多了。通俗叫做内存文件系统,只要服务器不重起数据将一直都在。
     通俗的来讲 redis、memcached是自己申请内存管理数据。当进程重启或者挂了就会丢失数据。quickdb是把实体数据储存在内存文件系统里的。当quickdb进程挂了,  实体数据依然还在。 一个进程可能因为各种原因比如修改了配置文件或者要调试数据。要经常重启。但是一个服务器不可能三天两天的重启或者死机。 一般服务器都是半年,或者 好几年都不重起的。 如果你的服务器经常断电或者死机重启那就不叫服务器了,叫家用电脑了。quickdb可以定期的从内存文件系统的数据同步到磁盘中去。这样当服务器重启,也不会丢失数据。 简单的来讲,进程可能会经常因为各种原因要重启或者挂了,但是服务器不可能经常重启或者死机。这样很大程度上保证了数据持久性,也保证了读写效率。做到鱼和熊掌兼得。
     quickDB Benchmark 性能测试
     写入3145739条数据 花费4.38秒  读取 3145739条数据花费3.88秒


quickdb下载地址:
http://code.google.com/p/loongsso/downloads/detail?name=quickdb-beta1.tar.bz2&can=2&q=#makechanges

Q: 既然是基于内存文件系统的,那leveldb、tokyocabinet等磁盘类的NOSQL可以直接使用了,为啥还用quickdb了?
A: leveldb、tokyocabinet是专门为硬盘特性而优化的NOSQL。比如增加了合并多个写为一次性写,并有内部的内存缓存系统。 如果使用内存文件系统的话,就会造成多次内存浪费。 quickdb不用缓存,不用合并写。做到简单就是快。

Q:  如果服务器内存不够大,是不是用不了quickdb
A:   内存不够大,也可以用quickdb。 内存文件系统可以用tmpfs。tmpfs是当内存不足的时候,把数据交换到swap区。

下面讲解了linux下的三种不同的内存文件系统类型:
(1)ramdisk,使用前需要先创建文件系统,并且调整文件系统大小比较麻烦,需要修改内核引导参数并重新启动操作系统,在繁杂多变的应用与需要 7X24不间断运行的系统来说,并不是一个可以接受的选择.好处是自2.0版本起内核便支持(这也算好处?嗯,确实算,如果你手头真有这样的系统的话)

(2)ramfs,使用前不需要去创建文件系统了,直接通过mount的方式即可挂载上来用,需要的时候可以使用"mount -o remount,maxsize=..."这种方式来调整大小.

(3)tmpfs,同ramfs在表面上基本上一样啦,不同于ramfs针对"物理内存",tmpfs是在虚拟内存下分配空间的,也就是说tmpfs实例中存储的文件既可能存在于物理内存中,也可能存在于交换分区中,具体存在哪里,是由"虚拟内存子系统"来调度的.

纯性能角度讲,ramfs会在进程占用内存使用较多的情况下会优于tmpfs,在没有交换分区或进程占用内存较小而不发生swap行为的情况下,两者性能不会有差异。

本期讨论话题:1,针对“怎么高效解决NOSQL数据库,数据持久性问题”这个话题分享您在实际生产中的解决方案,经验。
                    2,针对“七夜”带来的解决方案,进行讨论。
讨论时间:2012.1.10——2012.2.10
讨论有奖:     我们将对积极参与讨论的网友进行奖励,我们会对提出更优质方案的网友进行评选,优胜者(可以是多名)将获得CU十周年定制背包一个。
                   对积极参与活动网友(有效回复超过3贴),将获得由IBM笔记本内胆包一个(共5个)

十周年背包


IBM内胆包



作者: chenyx    时间: 2012-01-10 16:36
沙发支持下.
作者: 我要思考    时间: 2012-01-10 16:37
看着这个持久化解决方案,比redis的数据持久化 高速,效率。
作者: 无风之谷    时间: 2012-01-10 16:43
欢迎大家积极参与~!:wink:
作者: howlanderson    时间: 2012-01-10 16:46
相当给力啊,和redis有的一拼啊~~楼主实力!
作者: chenrvmldd    时间: 2012-01-10 16:47
这个在文件系统中有类似的做法,对于实时的文件系统,写内存,然后慢慢刷到磁盘中,但是LZ提的这个问题,从需求上来讲有矛盾。。。。我去找找以前做过这方面的优化的资料,到时候提出来讨论讨论
作者: howlanderson    时间: 2012-01-10 16:48
楼主不要忘了,把文档和售后工作做好啊,哈哈
作者: 瀚海书香    时间: 2012-01-10 16:49
回复 1# 无风之谷
关注NoSQL数据库话题

   
作者: lxvison    时间: 2012-01-10 16:49
太需要这东西了,晚上测试一下!~~
作者: dulcet    时间: 2012-01-10 16:49
马克
作者: 无风之谷    时间: 2012-01-10 16:51
chenrvmldd 发表于 2012-01-10 16:47
这个在文件系统中有类似的做法,对于实时的文件系统,写内存,然后慢慢刷到磁盘中,但是LZ提的这个问题,从 ...

欢迎讨论~!
作者: 李纳斯    时间: 2012-01-10 16:52
Q:quickdb是定时同步数据到实体硬盘上面的,上面说了服务器一般情况下不会断电或者重启,但是也不能保证没有意外情况发生如,内存条子坏掉,CPU过热等问题导致服务器重启或者宕机。那么距离下一次同步之前的数据也会丢失掉,这个目前还是无法避免的。期待完美解决数据丢失问题,可以当将quickdb用到存储持久性数据上了。目前好像还不支持分布式架构,期待下一个版本支持分布式。
作者: 无风之谷    时间: 2012-01-10 16:53
回复 8# 瀚海书香

瀚海参与下嘛!
   
作者: 李纳斯    时间: 2012-01-10 16:54
悲催的,刚发就被删掉

未命名.jpg (76.28 KB, 下载次数: 19)

未命名.jpg

作者: yanyangtian4502    时间: 2012-01-10 16:57
这个东西的开发接口 成熟吗 我很有兴趣啊
作者: chenyx    时间: 2012-01-10 16:57
放到内存里面,机器要是崩溃或者死锁了,那么数据不就是没了吗?
作者: chenyx    时间: 2012-01-10 17:01
嗯,一定要备份到实体存储介质上才靠谱.
备份的时间粒度和性能平衡点不好把握啊
作者: T-Bagwell    时间: 2012-01-10 17:09
其实掉电的问题好解决
关键是内存坏掉的问题不好搞

楼主确实很猛呀
作者: chenyx    时间: 2012-01-10 17:09
每天备份?
那么,要是碰上一个繁忙的服务器,在一天的某个时间down机了,那么,是不是意味着,整个1天的数据就over了呢?
作者: chenghy_boy    时间: 2012-01-10 17:19
:wink:顶一下!!!七夜说有背包送!不知道是不是坑我!
作者: dhlwing    时间: 2012-01-10 17:24
支持分布式? 支持读写分离?
作者: chenrvmldd    时间: 2012-01-10 18:11
回复 21# 七夜


    这个办法不错。。。。
作者: chenrvmldd    时间: 2012-01-10 18:13
回复 24# 七夜


    其实,我比较关注的,如果在系统负载率比较高的情况下,你还能不能保证你的读写效率,这方面有没有做过相关的测试了?
作者: wfcjz    时间: 2012-01-10 19:01
差点看成MYSQL
作者: renxiao2003    时间: 2012-01-10 22:40
本帖最后由 renxiao2003 于 2012-01-12 12:55 编辑
1,针对“怎么高效解决NOSQL数据库,数据持久性问题”这个话题分享您在实际生产中的解决方案,经验。

随着内存价格的降低,针对关系型数据库的ORM软件层出不穷,其原理就是先在内存区域开辟足够的空间来存储数据库的数据,然后在内存中操作这些数据,在需要时再批量将数据存储回关系数据库系统中。其实从这个方面来看,quickdb可能就是借签了关系数据库的这些ORM框架的经验来实现的。但关系数据库最终存储的也是系统文件,只是在中间架构了一些DBMS系统来管理这些系统文件,而不是由ORM框架来直接操作系统文件。quickdb只是相当于在ORM框架和系统文件中省略了DBMS而已。是否可以将quickdb看成是NOSQL的相当于ORM的框架实现呢?
现在的NOSQL有基于内存的,也有基于磁盘的。那么如果有一个框架来实现从内存和磁盘的MAP,那么就可以提高磁盘NOSQL的性能了。只是目前的NOSQL属于百家争鸣阶段,还没有形成统一的标准,所以想开发一个兼容多种NOSQL的MAP框架就比较有难度了啊。这也是NOSQL目前发展的瓶颈了吧。
2,针对“七夜”带来的解决方案,进行讨论。

“七夜”提供的这个quickdb确实是一个不错的能提高NOSQL的性能的“家伙”,可惜如第一条叙述的一样,正是因为目前NOSQ的百家争鸣,没有统一的标准,所以quickdb也只能适用自己的系统,如果业界能定义出NOSQL的统一的标准,我想某一天,quickdb就可以兼容所有的NOSQL系统,这样我们也不用刻意的去区分到底是内存型的NOSQL还是磁盘型的NOSQL了。就像当今的HIBERNAT一样,我一下子就兼容了所有的关系数据库软件,只要你使用“我”,就不用去特意考虑底层RDBMS的不同。“我”已经帮你考虑完了。期待NOSQL也有能这么一天。
作者: hellioncu    时间: 2012-01-11 11:45
应用程序还是要通过read/write访问数据,就像访问普通文件一样?这样应用程序一般来说还得在内存中维护一份数据,有没有办法减少内存的占用和复制呢?
作者: hellioncu    时间: 2012-01-11 13:39
看了下代码,跟我想象的不是一回事
作者: hellioncu    时间: 2012-01-11 15:23
在我的RHEL 5.3 x86_64编译错误,是pstdint.h中的一些定义类型冲突,懒得去弄了。
似乎是hash的key等信息用mmap,value 写到另外的数据文件中。这样进程挂了并不能保证mmap中的数据是正确的,有可能其中的某些长度数据错误,导致数据文件解析错误,整个HashTable都无法恢复。
作者: lnbalife    时间: 2012-01-11 17:53
redis好像也是定期刷到磁盘里吧
作者: hellioncu    时间: 2012-01-11 20:58
七夜 发表于 2012-01-11 16:55
任何一个nosql,都会有索引文件和实体数据文件的。 像key-value数据库,都是通过key的索引去查找数据的 ...


在你的实现中我没找到这方面的考虑呀
作者: liguangyi    时间: 2012-01-12 09:58
网上有不少成熟的应用了,为何还要重新造轮子?比如著名的berkeleydb,fastdb,GigaBASE,gdbm,qdbm 等等,至少这几个是都是我以前用过或者测试过的,这些项目也发展了几年,也相当完善了。楼主的这个  quickdb ,有何特点及优势 ?


作者: sdsuper    时间: 2012-01-13 14:30
关注一个
作者: donald131    时间: 2012-01-13 21:35
我下载下来好像解压错误

!   C:\Documents and Settings\Administrator\My Documents\Downloads\quickdb-beta1.tar.bz2: 无法创建 shm\jemalloc-2.2.5\include\jemalloc\internal\prn.h

作者: donald131    时间: 2012-01-13 21:38
抱歉 我2了
作者: kns1024wh    时间: 2012-01-14 11:54
回复 1# 无风之谷


    nosql 是做互联网的运维朋友要和hadoop一同关注的技术,从lvs mysql的技术演进
作者: quwei197874    时间: 2012-01-20 09:12
leveldb也是一款很好的nosql,即是内存又是硬盘型的
作者: nokianihao    时间: 2012-01-22 18:02
以memcached为例,从设计角度上它是没有数据冗余环节的,其本身作为一个大规模的高性能cache层,加入数据冗余所能带来的只有设计的复杂性和提高系统的开支。当一个ms上丢失了数据之后,app还是可以从数据库中取得数据。不过更谨慎的做法是在某些ms不能正常工作时,提供额外的ms来支持cache,这样就不会因为app从cache中取不到数据而一下子给数据库带来过大的负载。同时为了减少某台ms故障所带来的影响,可以使用“热备份”方案,就是用一台新的ms来取代有问题的ms,当然新的ms还是要用原来ms的IP地址,大不了数据重新装载一遍。

另外一种方式就是提高ms的节点数,然后mc会实时侦查每个节点的状态,如果发现某个节点长时间没有响应,就会从mc的可用server列表里 删除,并对server节点进行重新hash定位。当然这样也会造成的问题是,原本key存储在B上,变成存储在C上了。所以此方案本身也有其弱点,最好 能和“热备份”方案结合使用,就可以使故障造成的影响最小化。

其实若从功能上看,dbcached和Memcached是一样的,前者是一款基于Memcached和NMDB的分布式key-value数据库内存缓存系统,兼容性极佳,Memcached 能做的,dbcached 都能做。除此之外,dbcached 还将“Memcached、持久化存储管理器、NMDB 客户端接口”在一个程序中结合起来,对任何原有 Memcached 客户端来讲,dbcached 仍旧是个 Memcached 内存对象缓存系统,但是它的数据可以持久存储到本机或其它服务器上的 QDBM 或 Berkeley DB 数据库中。
性能上前端 dbcached 的并发处理能力跟 Memcached 相同;后端 NMDB 跟 Memcached 一样,采用了libevent 进行网络IO处理,拥有自己的内存缓存机制,性能不相上下。

写入方面当“dbcached 的 Memcached 部分”接收到一个 set(add/replace/...) 请求并储存 key-value 数据到内存中后,“dbcached 持久化存储管理器”能够将 key-value 数据通过“NMDB 客户端接口”保存到 QDBM 或 Berkeley DB 数据库中。

读取方面当“dbcached 的 Memcached 部分”接收到一个 get(incr/decr/...) 请求后,如果“dbcached 的 Memcached 部分”查询自身的内存缓存未命中,则“dbcached 持久化存储管理器”会通过“NMDB 客户端接口”从 QDBM 或 Berkeley DB 数据库中取出数据,返回给用户,然后储存到 Memcached 内存中。如果有用户再次请求这个 key,则会直接从 Memcached 内存中返回 Value 值。在命中的情况下,读取数据的速度跟普通的 Memcached 无差别,速度一样快。

使用 dbcached不用担心 Memcached 服务器死机、重启而导致数据丢失。即使因为故障转移,添加、减少 Memcached 服务器节点而破坏了“key 信息”与对应“Memcached 服务器”的映射关系也不怕。dbcached 和 NMDB 既可以安装在同一台服务器上,也可以安装在不同的服务器上,多台 dbcached 服务器可以对应一台 NMDB 服务器,其对于“读”大于“写”的应用尤其适用。

目前大部分 NOSQL 实现都基于数据副本的热备份来保证连续的高可用性即保存同一数据的多个副本。一些实现提供了API,可以控制副本的复制,也就是说,当存储一个对象的时候,你可以在对象级指定你希望保存的副本数。通过对数据进行分区可以将失效带来的影响最小化,也将读写操作的负载分布到了不同的机器上。如果一个节点失效了,只有该节点上存储的数据受到影响,而不是全部数据。
同时其提供了不停机或完全重新分区的扩展集群的方法以掌控不断增长的数据。一个算法会在节点加入或失效时通知某一分区的邻居。仅有这些节点受到这一变化的影响,而不是整个集群。

总的来说,伸缩性优先应用是那些必须具备无限可伸缩性的应用,能够不受限制的扩展比更丰富的功能更加重要,在节省人力成本方面这已经是未来技术发展的必然趋势。
  
作者: Darleter    时间: 2012-02-14 08:52
喜欢这帖子。
七夜的blog我也很喜欢。
作者: witer666    时间: 2012-02-28 23:24
好的冗灾,好的共享内存,好的数据热备
作者: lihualoveyou    时间: 2012-03-07 11:18
回复 22# T-Bagwell
个人觉得,要解这个问题可以从系统层做文章。
可以通过掉电保护单元(BBU)解决宕机后数据丢失问题。比如,掉电重启后,先把内存的数据刷到硬盘上。
内存坏掉的话,可以做内存镜像,不过有点难度,需要对内存管理机制进行调整,确保镜像确实是在两条不同的内存条上。或者干脆所有的内存都mirror.

感觉超出了这个软件需要解决的范围了,呵呵


   
作者: T-Bagwell    时间: 2012-03-07 13:07
lihualoveyou 发表于 2012-03-07 11:18
回复 22# T-Bagwell
个人觉得,要解这个问题可以从系统层做文章。
可以通过掉电保护单元(BBU)解决宕机 ...

掉电重启以后内存中的数据还会存在?
作者: lihualoveyou    时间: 2012-03-07 16:37
T-Bagwell 发表于 2012-03-07 13:07
掉电重启以后内存中的数据还会存在?

通用的服务器估计不行,BIOS启动之后好像会有初始化内存的操作。不过,现在的磁盘阵列都是用这种方式来保证缓存数据不丢失的。
作者: hobbs136    时间: 2012-03-09 16:38
第一 我觉得不要试图去搞一些nosql不擅长的功能,例如保证acid的事务特性。
第二 我认为你的持久化方案简直是糟糕透顶了。我逐条分析
1.
"什么是内存文件系统了?就是操作系统把系统内存划出一部分当作硬盘使用。你可以像操作磁盘那样的操作内存。但效率远远比硬盘来的快多了"
首先相比直接操作内存来说,这增加了代码的复杂度。用文件形式存储key和value,那你不得不自己去管理偏移量了,可能你选择管理空闲块链表,
但是无论如何,这都会增加代码量,增加cpu的处理周期。
"当quickdb进程挂了,实体数据依然还在。一个进程可能因为各种原因比如修改了配置文件或者要调试数据。要经常重启。但是一个服务器不可能三天两天的重启或者死机。 一般服务器都是半年,或者好几年都不重起的。如果你的服务器经常断电或者死机重启那就不叫服务器了,叫家用电脑了。quickdb可以定期的从内存文件系统的数据同步到磁盘中去。这样当服务器重启,也不会丢失数据"
上面这句话毛病最多。"进程挂了,实体数据依然还在,这根本不算一个优点"。设计良好的服务程序怎么可能自己挂掉了?那么多nosql数据库都没有提过这点。那么多sql数据库也没有提过这点。修改配置文件或者调试数据,要经常重启。靠,进程正常结束时操作系统会将所有需要持久化的数据冲刷进硬盘的。
  "但是一个服务器不可能三天两天的重启或者死机。一般服务器都是半年,或者好几年都不重起的。如果你的服务器经常断电或者死机重启那就不叫服务器了,叫家用电脑了"。 这好像是服务器推销员的口吻。各种数据库要考虑的就是非正常宕机的情况,虽然宕机的几率很低,但是各种数据库都为此牺牲了很多。但是这个quickdb却不是,且看下面这句话。
  "quickdb可以定期的从内存文件系统的数据同步到磁盘中去,这样当服务器重启,也不会丢失数据"。就这句话,你都没说这个时间窗口到底是多大,用户到底会损失多少数据啊。
  
  "这样很大程度上保证了数据持久性,也保证了读写效率。做到鱼和熊掌兼得"。这句话完全不靠谱。因为下面又说,每天备份一次,苍天,我还是用我的redis好了。
  
第三 那个测试毫无意义,因为没有考虑并发这种情况。
第四 还需要特殊的运维操作,就是创建内存文件系统,增加系统整体复杂度。
第五 看着那个id为“我要思考”的家伙的留言我就想笑,他大概是刚开始思考。
第六 我的建议
认清各种事物的用途,没有一个nosql数据库用内存文件系统来存储文件,所以不要标新立异。潜下心来,好好读一下开源程序的代码。从设计上,利用现有的软件解决实际中的问题。现在存储的问题就是cap的问题,请沿着这个方向走。
作者: hitsubunnu    时间: 2012-03-09 17:05
hobbs136 发表于 2012-03-09 16:38
第一 我觉得不要试图去搞一些nosql不擅长的功能,例如保证acid的事务特性。
第二 我认为你的持久化方案简直 ...


就这位兄弟说的话 靠谱
作者: jiyuwoaa    时间: 2012-04-03 21:09
支持~!!!!!!!!!!
作者: 大邪神    时间: 2012-04-06 12:08
不用啊
作者: epstar    时间: 2012-11-19 10:26
谢谢楼主啊,受益匪浅啊!




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2