Doozer consistency guarantees

161 views
Skip to first unread message

Petar Maymounkov

unread,
Mar 30, 2012, 11:26:25 AM3/30/12
to doo...@googlegroups.com
Dear all, I just read Doozer's doc in order to do a head-to-head comparison and evaluation against Zookeeper.

From the REV-related guarantees described for each command, I gather that all clients are guaranteed the
same consistent view of the db. Correct?

This probably comes at a speed cost compared to Zookeeper where consistency is guaranteed on a per-client
basis. Correct?

Has anyone made head-to-head performance measurements?

To the authors: Can you provide a pointer to the respective algorithmic literature describing the
consensus algorithm used? Is it the chubby paper? Other?

Thanks,
Petar

Blake Mizerany

unread,
Mar 30, 2012, 5:27:17 PM3/30/12
to doo...@googlegroups.com
On Fri, Mar 30, 2012 at 8:26 AM, Petar Maymounkov <pet...@gmail.com> wrote:
> Dear all, I just read Doozer's doc in order to do a head-to-head comparison
> and evaluation against Zookeeper.
>
> From the REV-related guarantees described for each command, I gather that
> all clients are guaranteed the
> same consistent view of the db. Correct?

For consistant reads across requests per doozerd/client (i.e. seeing
the same tree across multiple requests on any doozerd), pass the REV
for the tree you want to see.

>
> This probably comes at a speed cost compared to Zookeeper where consistency
> is guaranteed on a per-client
> basis. Correct?

We don't have benchmarks to say either way.

> Has anyone made head-to-head performance measurements?
>
> To the authors: Can you provide a pointer to the respective algorithmic
> literature describing the
> consensus algorithm used? Is it the chubby paper? Other?

PAXOS is the algorithm for consensus.

> Thanks,
> Petar
>

Petar Maymounkov

unread,
Mar 30, 2012, 6:03:19 PM3/30/12
to doo...@googlegroups.com
Thanks Blake.

I am actually going to implement a benchmark against Zookeeper and will be more than 
happy to share the results and do a post and so forth.

However, I am noticing that the current sources don't compile. Now, with minor mostly build-related
fixes (and getting rid of the websocket logic) things do compile. I have not yet started actually
testing (and don't know what else might pop out).

But I was wondering whether the state of doozer (being not to sync with Go1) is 
indicative of a larger problem. Is the product not actively maintained?

Please let me know. As I am taking it under serious consideration.

Thanks,
Petar

Aram Hăvărneanu

unread,
Mar 30, 2012, 6:19:31 PM3/30/12
to doo...@googlegroups.com
I have sent pull requests to bring doozer and doozerd to Go1: 

https://github.com/ha/doozerd/pull/28
https://github.com/ha/doozer/pull/12

Aram Hăvărneanu

unread,
Mar 30, 2012, 6:21:28 PM3/30/12
to doo...@googlegroups.com

Petar Maymounkov

unread,
Apr 2, 2012, 9:11:50 AM4/2/12
to doo...@googlegroups.com
Thanks for the patched version of doozerd. It works :)

I will take a look at your persistent solution as well.

Petar

Petar Maymounkov

unread,
Apr 2, 2012, 12:24:07 PM4/2/12
to doo...@googlegroups.com
I've ran into two problems, maybe someone can resolve the issues for me:

(1) if I execute a SET with a body larger than 2000 (or so) bytes, the client
blocks and server seems unusable afterwards. Smaller SETs are fine.

(2) I am not sure how to make a directory. I execute a
Set("/name", rev, nil) and then try
Set("/name/a0", rev, body) and I get a NOTDIR error.

I've tried replacing the nil with make([]byte, 0) and so forth
and I always get the same error.

Thanks
Petar

Blake Mizerany

unread,
Apr 2, 2012, 12:46:41 PM4/2/12
to doo...@googlegroups.com, doo...@googlegroups.com
Directories are created when files are set. No need to explicitly create them.

Petar Maymounkov

unread,
Apr 2, 2012, 3:49:41 PM4/2/12
to doo...@googlegroups.com
I understand this, but the following code, when run on a fresh server, does not seem to do what you suggest:

package main
import(
"fmt"
"os"
)
func main() {
dzr, err := doozer.Dial("127.0.0.1:8040")
if err != nil {
fmt.Printf("dial (%s)", err)
return
}
defer dzr.Close()

_, err = dzr.Set("/x0", 1000, nil)
if err != nil {
fmt.Fprintf(os.Stderr, "set /x0 (%s)\n", err)
os.Exit(1)
}
fmt.Printf("ok1\n")
_, err = dzr.Set("/x0/tom", 1000, nil)
if err != nil {
fmt.Fprintf(os.Stderr, "set /x0/tom (%s)\n", err)
os.Exit(1)
}
fmt.Printf("ok2\n")
}

Produces the following undesirable output:

ok1
set /x0/tom (NOTDIR)
exit status 1

Am I doing something wrong?

Thanks
Petar

Blake Mizerany

unread,
Apr 2, 2012, 3:55:26 PM4/2/12
to doo...@googlegroups.com
Yes. Doozer's file datastore works like the unix filesystem:

$ touch foo
$ mkdir foo/bar
mkdir: foo: Not a directory

Petar Maymounkov

unread,
Apr 2, 2012, 4:06:33 PM4/2/12
to doo...@googlegroups.com
I am sorry. This seems to contradict what you said before.

Could you, please, give me an example how to create a directory
"/a" and a file "b" inside of it, using the Go routines supplied by the
doozer library.

Thank you
Petar

Blake Mizerany

unread,
Apr 2, 2012, 4:12:35 PM4/2/12
to doo...@googlegroups.com
If you want /a/b, then you SET /a/b = 'something'. If you SET /a
first, then /a/b cannot exist because /a is a file.

Bobby Powers

unread,
Apr 2, 2012, 12:35:54 PM4/2/12
to doo...@googlegroups.com
My understanding is directories are transient - you simply make files and any directories are created along the way.  Directories also seem to be garbage collected - when all the files in a directories are deleted, the directory is removed.

Blake Mizerany

unread,
Apr 2, 2012, 4:20:21 PM4/2/12
to doo...@googlegroups.com
That is correct.

Petar Maymounkov

unread,
Apr 2, 2012, 1:34:07 PM4/2/12
to doo...@googlegroups.com
Yes, but an error NOTDIR occurs on the second Set below:

package main
import(
"fmt"
"os"
"github.com/4ad/doozer"
)
func main() {
dzr, err := doozer.Dial("127.0.0.1:8040")
if err != nil {
fmt.Printf("dial (%s)", err)
return
}
defer dzr.Close()

_, err = dzr.Set("/x0", 6000, nil)


if err != nil {
fmt.Fprintf(os.Stderr, "set /x0 (%s)\n", err)
os.Exit(1)
}

_, err = dzr.Set("/x0/tom", 6000, nil)


if err != nil {
fmt.Fprintf(os.Stderr, "set /x0/tom (%s)\n", err)
os.Exit(1)
}

fmt.Printf("ok\n")

Petar Maymounkov

unread,
Apr 2, 2012, 4:44:00 PM4/2/12
to doo...@googlegroups.com
Got it. Thank you.

What about the second issue:

Setting bodies of size 3000 bytes seems to block the client
and the server.

Blake Mizerany

unread,
Apr 2, 2012, 4:46:56 PM4/2/12
to doo...@googlegroups.com
Bodies must be within what a UDP packet can hold. You're probably hitting your networks limit. Try to keep them under 1k.
Reply all
Reply to author
Forward
0 new messages