小编Riy*_*lla的帖子

数据库索引的排序字符串表(SSTable)或B +树?

使用两个数据库来说明这个例子:CouchDBCassandra.

CouchDB的

CouchDB使用B + Tree作为文档索引(使用巧妙的修改在其仅附加环境中工作) - 更具体地说,当文档被修改(插入/更新/删除)时,它们被附加到正在运行的数据库文件以及完整的Leaf - >文档后面的更新版本对受影响的所有节点的B +树的节点路径.

这些分段修改的索引修订与修改一起内联,使得完整索引是附加在文件末尾的最新索引修改的联合,以及在数据文件中进一步返回的仍然相关的附加部分,并且尚未修改.

搜索B +树是O(logn).

卡桑德拉

Cassandra将记录键在内存中保存在表中(让我们将它们视为此问题的数组),并将它们作为单独的(已排序的)排序字符串表不时写出来.

我们可以将所有这些表的集合视为"索引"(根据我的理解).

Cassandra需要不时地压缩/组合这些排序字符串表,从而创建索引的更完整的文件表示.

搜索已排序的数组是O(logn).

假设在CouchDB中维护部分B +树块与Cassandra中的部分排序字符串索引之间存在类似的复杂程度,并且假设两者都提供O(logn)搜索时间,您认为哪一个可以更好地表示数据库索引以及为什么?

我特别好奇是否有一个关于一个的实现细节使它特别有吸引力,或者如果它们都是一个清洗,你只需选择你喜欢使用的数据结构/对开发人员更有意义.

谢谢你的想法.

database indexing couchdb cassandra nosql

41
推荐指数
3
解决办法
2万
查看次数

用于数据库实现的内存映射MappedByteBuffer或Direct ByteBuffer?

由于所有上下文,这看起来像一个很长的问题.下面小说中有两个问题.感谢您抽出宝贵时间阅读本文并提供帮助.

情况

我正在开发一个可扩展的数据存储区实现,它可以支持在32位或64位系统上处理从几KB到TB或更大的数据文件.

数据存储区采用Copy-on-Write设计; 始终将新数据或修改后的数据附加到数据文件的末尾,并且永远不会对现有数据进行就地编辑.

系统可以托管1个或多个数据库; 每个由磁盘上的文件表示.

实施细节并不重要; 唯一重要的细节是我需要不断附加到文件并将其从KB增加到MB,再增加到GB到TB,同时随机跳过文件以进行读取操作以回答客户端请求.

首先,思考

乍一看,我知道我想使用内存映射文件,因此我可以将有效管理数据的内存中状态的负担推到主机操作系统和我的代码之外.

然后我的所有代码都需要担心的是在写入时序列化附加到文件的操作,并允许任意数量的同时读者在文件中搜索以回答请求.

设计

因为单个数据文件可以超过MappedByteBuffer的2GB限制,所以我希望我的设计必须包含一个抽象层,它采用写入偏移并将其转换为特定2GB段内的偏移量.

到现在为止还挺好...

问题

这是我开始被挂起的地方,并认为采用不同的设计(下面提出)可能是更好的方法.

通过在SO上阅读20个左右的"内存映射"相关问题,似乎mmap调用对于在分配时想要连续的内存运行是敏感的.所以,例如,在32位主机操作系统上,如果我试图mmap 2GB文件,由于内存碎片,我的机会很小,映射将成功,而我应该使用像一系列128MB映射的东西来拉动整个档案.

当我想到这个设计时,甚至说使用1024MB mmap大小,对于托管几个庞大数据库的DBMS,所有数据都由1TB文件表示,我现在在内存中有数千个内存映射区域,在我自己的Windows 7测试中尝试为了在多GB文件中创建几百个mmaps,我不仅遇到了异常,每次我尝试分配太多时实际上让JVM陷入段错误,并且在一个案例中我在Windows 7机器中获得了视频切断并重新初始化我以前从未见过的操作系统错误弹出窗口.

无论"你永远不会处理那么大的文件"或"这是一个人为的例子"的论点,我可以用这些类型的副作用编写代码的事实使我的内部警报处于高度警戒状态.考虑替代impl(下面).

BESIDES问题,我对内存映射文件的理解是每次文件生成时我都必须重新创建映射,所以在这个文件只是在设计中附加的情况下,它实际上在不断增长.

我可以通过在块中增加文件(一次说8MB)来解决这个问题,并且每8MB重新创建一次映射,但是不断重新创建这些映射的需要让我感到紧张,特别是没有明确的unmap功能Java支持.

问题#1 of 2

鉴于我到目前为止的所有发现,我会将内存映射文件视为主要读取重量级解决方案或只读解决方案的良好解决方案,但考虑到需要不断重新创建映射,我认为这不是写入量大的解决方案.

然后我看看我周围的景观,像MongoDB这样的解决方案拥抱整个地方的内存映射文件,我觉得我在这里缺少一些核心组件(我知道它一次分配2GB范围,所以我想他们正在利用这种逻辑来解决重映射成本问题并帮助维持磁盘上的顺序运行.

在这一点上,我不知道问题是Java是否缺少unmap操作,这使得它更加危险并且不适合我的用途,或者如果我的理解不正确并且有人可以指向我North.

替代设计

如果我对mmap的理解是正确的,我将在上面提出的内存映射的另一种设计如下:

定义一个合理可配置大小的直接ByteBuffer(粗略地为2,4,8,16,32,64,128KB),使其可以轻松地与任何主机平台兼容(不需要担心DBMS本身导致颠簸的情况)并使用原始的FileChannel,一次执行文件1 buffer-capacity-chunk的特定偏移读取,完全放弃内存映射文件.

缺点是现在我的代码必须担心诸如"我从文件中读取足够的内容以加载完整记录吗?"

另一个缺点是我无法利用操作系统的虚拟内存逻辑,让它自动为我保留更多"热"内存数据; 相反,我只是希望操作系统使用的文件缓存逻辑足够大,可以在这里为我做一些有用的事情.

问题#2 of 2

我希望能够确认我对所有这一切的理解.

例如,文件缓存可能很棒,在两种情况下(内存映射或直接读取),主机操作系统将保留尽可能多的热数据,大文件的性能差异可以忽略不计.

或许我对内存映射文件(连续内存)的敏感要求的理解是不正确的,我可以忽略所有这些.

java file-io database-design bytebuffer memory-mapped-files

21
推荐指数
1
解决办法
1万
查看次数

使用sun.misc.Unsafe,从Direct ByteBuffer扫描字节的最快方法是什么?

背景

假设我有一个直接的ByteBuffer:

ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024);
Run Code Online (Sandbox Code Playgroud)

并假设我将缓冲区传递给AsynchronousSocketChannel以从该套接字读取数据块,一次最多X个字节(此处示例中为1024).

从套接字到直接 ByteBuffer 的传输时间非常棒,因为它全部发生在本机OS内存空间中; 我还没有通过JVM"血脑"屏障......

假设我的工作是扫描从直接字节缓冲区读回的所有字节,我这样做的最快方法是什么?

我最初问" ......利用sun.misc.Unsafe "但也许这是错误的假设.

可能的方法

我目前看到三种方法,我最感兴趣的是#3:

  1. (DEFAULT)使用ByteBuffer的bulk-get将字节从本机OS空间直接拉入内部字节[1024]结构.
  2. (UNSAFE)使用Unsafe的getByte操作直接从ByteBuffer中提取值,跳过ByteBuffer的标准get操作的所有边界检查.Peter Lawrey 在这里的答案似乎表明,Unsafe中的原始本机方法甚至可以通过JIT编译器("内在函数")优化为单机指令,从而实现更加出色的访问时间.(=== UPDATE ===有趣的是,看起来底层的DirectByteBuffer类与那些感兴趣的get/put操作完全相同.)
  3. (BANANAS)在一些犯罪与人类有关的方式中,使用Unsafe,我可以将直接ByteBuffer 的内存区域复制到我的字节[1024]存在于VM内部的相同内存地址,并开始访问数组使用标准的int索引?(这假设"copyMemory"操作可能会在操作系统级别进行奇妙优化.

我确实认为,假设copyMemory操作正是它所宣传的内容,即使在更优的操作系统空间中,上面的#2方法可能仍然是最优化的,因为我没有在开始处理之前创建缓冲区的重复项它.

这与" 我可以使用不安全迭代字节[]更快吗? "问题不同,因为我甚至没有计划在内部将字节拉入字节[],如果没有必要的话.

谢谢你的时间; 只是好奇,如果有人(彼得?)已经疯狂与不安全做这样的事情.

java performance bytebuffer unsafe

11
推荐指数
1
解决办法
2373
查看次数

如何在Node.JS中限制(或队列)对外部进程的调用?

脚本

我有一个Node.JS服务(使用ExpressJS编写),通过DnD接受图像上传(示例).上传图片后,我会做一些事情:

  1. 从中提取EXIF数据
  2. 调整大小

这些调用目前正通过node-imagemagick模块处理,我的代码如下所示:

app.post('/upload', function(req, res){
  ... <stuff here> ....

  im.readMetadata('./upload/image.jpg', function(err, meta) {
      // handle EXIF data.
  });

  im.resize(..., function(err, stdout, stderr) {
      // handle resize.
  });
});
Run Code Online (Sandbox Code Playgroud)

正如你们中的一些人已经发现的那样,问题在于,如果我获得足够的同步上传,那么每个上传都会产生一个"身份"调用,然后是一个调整大小操作(来自Image Magick),有效地在高负载下杀死服务器.

只是用ab -c 100 -n 100锁定我的小512 Linode dev服务器进行测试,这样我就不得不强行重启.我知道我的测试可能只是服务器的负载太多,但我想要一个更强大的方法来处理这些请求,所以我有一个更优雅的失败,然后总VM自杀.

在Java中,我通过创建一个固定线程ExecutorService来解决这个问题,该ExecutorService将工作排队并在最多X个线程上执行它.

在Node.JS中,我甚至不确定从哪里开始解决这样的问题.我的大脑并没有完全围绕非线程性质,以及我如何创建一个异步JavaScript函数来排队工作,而另一个......(线程?)处理队列.

关于如何思考这个或如何处理这个的任何指针将不胜感激.

附录

这与关于FFMpeg的这个问题不同,虽然我想这个人一旦他的webapp处于负载状态就会有这个完全相同的问题,因为它归结为同样的问题(同时触发过多的同时本机进程).

javascript queue node.js

8
推荐指数
1
解决办法
2240
查看次数

如何使用Enums的简单性设计易于扩展的API?

对不起,标题含糊不清; 我想不出如何更清楚地说出来.以下是问题的重点:

强调

  • 询问有关ExifTool for Java库的API设计问题.
  • 以下是当前API 的示例.
  • 作为USER,API使用起来非常简单,因为您只需传入Enums以获取您想要的图像元数据.
  • 作为DEV,API有点糟糕,因为您无法使用更多Enum类型轻松扩展基类以支持lib中可能不直接支持的其他元数据.
  • 简单地预定义和支持" 所有元数据 "并非易事.

鉴于设置信息,我所追求的是试图找到一种方法来预先定义人们通常想要从他们的图像中获得的30或40个最常见的元数据标记; 现在一切都被定义为枚举,但是这种类不可扩展.

如果我使用"每元数据类标记"路由,则可扩展性将很简单,但是开箱即用的API将不那么友好.

如果闭包提供了一个非常漂亮和简单的解决方案,我会考虑制作这个Java 8+库的v2.0,否则我显然更愿意让它与更多系统(Java 6/7)兼容而不是更少.

摘要

我对库的目标是"易于使用和扩展" - 我觉得我已经在1.x版本中使用了"简单易用"的方面,但是库不容易扩展,我想在2.x系列.

我已经坐在2.x版本上超过一年等待灵感罢工,它已经躲过了我; 我希望有人可以发现我的错误,我可以以非常优雅的方式向前移动lib.

谢谢你们的时间!

java api frameworks exif

7
推荐指数
1
解决办法
1460
查看次数

Java NIO:如何知道SocketChannel read()何时完成非阻塞I/O.

我目前正在使用非阻塞SocketChannel(Java 1.6)充当Redis服务器的客户端.Redis直接在套接字上接受纯文本命令,由CRLF终止并以类似方式响应,这是一个简单的例子:

发送:'PING\r \n'

RECV:'+ PONG\r \n'

Redis还可以返回大量回复(取决于您要求的内容),其中许多\ r \n终止数据部分都作为单个响应的一部分.

我使用标准while(socket.read()> 0){// append bytes}循环从套接字读取字节并将它们重新组装到客户端进行回复.

注意:我没有使用Selector,只是连接到服务器的多个客户端SocketChannel,等待服务发送/接收命令.

我感到困惑的是合同中的SocketChannel.read()在非阻塞模式的方法,特别是如何知道什么时候该服务器进行发送,我有整个邮件.

我有一些方法可以防止返回太快并让服务器有机会回复,但我坚持的一件事是:

  1. 是否有可能read()返回字节,然后在后续调用返回没有字节,但在另一个后续调用再次返回一些字节?

基本上,如果我收到至少1个字节并且最终read()返回0然后我知道我已经完成了,或者可能服务器只是忙碌而且可能会丢弃一些如果我等待并继续尝试更多的字节?

如果它仍然可以继续发送字节,即使read()返回0字节(之前成功读取后),那么我不知道如何告诉服务器何时完成与我交谈,事实上我很困惑如何java.io.*样式通信甚至可以知道服务器何时"完成".

你们知道read永远不会返回-1,除非连接已经死了,这些都是标准的长期数据库连接,所以我不会在每次请求时关闭并打开它们.

我知道一个受欢迎的反应(至少对于这些NIO问题)一直在看Grizzly,MINA或Netty - 如果可能的话,我真的想在采用第三方依赖之前了解这一切是如何工作的.

谢谢.

奖金问题:

我原本以为阻塞SocketChannel就是这样的方式,因为我不想让调用者做任何事情,直到我处理他们的命令然后给他们回复.

如果这最终成为一种更好的方法,只要没有足够的字节来填充给定的缓冲区,我就会看到SocketChannel.read()阻塞,我有点困惑...没有逐字节读取所有内容我无法弄清楚这个默认行为是如何实际使用的......我从来不知道从服务器返回的回复的确切大小,所以我对SocketChannel.read()的调用总是阻塞直到超时(此时我终于看到内容位于缓冲区中了.

我不清楚使用阻塞方法的正确方法,因为它总是挂起来读取.

java nio nonblocking socketchannel

6
推荐指数
1
解决办法
1万
查看次数

CouchDB中的基本HTTP身份验证是否足够安全,可以跨EC2区域进行复制?

我可以理解,在同一句话中看到"基本认证"和"足够安全"很像阅读"没有降落伞跳伞仍然安全吗?",所以我会尽力澄清我所得到的.

从我在网上看到的情况来看,人们通常将基本的HTTP身份验证描述为由于证书以明文形式从客户端传递到服务器而不安全; 这使得您可以通过网络配置中的恶意人员或中间人嗅探您的凭据,您的流量可能会通过不受信任的访问点(例如,咖啡店的开放式AP).

为了保证您与服务器之间的对话安全,解决方案通常是使用基于SSL的连接,您的凭据可能以纯文本形式发送,但您和服务器之间的通信通道本身是安全的.

所以,在我的问题上......

在将一个CouchDB实例从一个区域(例如us-west)中的EC2实例复制到另一个区域(例如新加坡)的另一个CouchDB实例的情况下,网络流量将穿过我认为"可信"主干的路径服务器.

鉴于(假设我没有复制高度敏感的数据),任何人/每个人都会认为CouchDB复制的基本HTTP身份验证足够安全吗?

如果没有,请说明我在这里缺少哪些方案会使这种设置无法接受.我确实理解敏感数据这是不合适的,我只想更好地理解在相对可信赖的网络上复制的非敏感数据的细节.

security authentication replication couchdb http

6
推荐指数
1
解决办法
1617
查看次数

CouchDB Replication如何与失败/恢复服务器一起运行?

请考虑以下情形:

3个EC2实例位于:

  • US-WEST
  • 爱尔兰
  • 东京

每个实例都是专用的CouchDB服务器.每个CouchDB服务器都设置为与每个其他服务器(双向)运行连续复制.

现在假设由于某些AWS中断,Ireland服务器脱机.US-WEST和Tokyo CouchDB服务器将重试X次,然后最终无法使用该服务器进行复制(这是正确的吗?)

让我们说6个小时过去,AWS让该地区重新上线,该服务器重新启动 - 我认为US-WEST和东京将忽略爱尔兰的服务器,直到爱尔兰CouchDB服务器重新启动与两者的双向同步他们,一个la:

Irish CouchDB _replicator Pseudo-Settings

  • 复制[源=本地主机,目标= US-西]
  • 复制[源=我们走向,目标=本地主机]
  • 复制[源=本地主机,目标=东京]
  • 复制[源=东京,目标=本地主机]

Q1:我对Couch复制失败/恢复的理解是否正确?

Q2:如果网络故障在一小时后自行修复(具体是:没有服务器重启,迫使数据库在启动时重新启动),该怎么做各个CouchDB实例对此做出反应怎么办?我想我们西方和东京会忘记爱尔兰,但是爱尔兰是否会突然再次与这两台服务器交谈,重新初始化双向连续复制?

我对EC2环境中的故障​​恢复特别感兴趣,所以如果我错过了该环境的具体细节,请告诉我.

谢谢!

replication recovery couchdb amazon-ec2 amazon-web-services

5
推荐指数
1
解决办法
1047
查看次数