如何独立使用 bitcask

发布于 2024-12-29 09:49:05 字数 3066 浏览 1 评论 0原文

(编辑:我错过了创建 bitcask 标签的一些声誉,所以...)

tl;dr => bitcask:get/2 不起作用并在 bitcask_nifs:keydir_get_int 中引发 badarg)

我会想知道如何在没有 riak 的情况下以正确的方式使用 bitcask。

首先,我尝试这样做:

bitcask:put(Handle, 3, {this, is, data}).
bitcask:get(Handle, 3).

这两个调用引发相同的错误: badarg 和 erlang:size/1

问题是 erlang:size/1 只接受二进制文件或元组。 所以我正在尝试这个:

bitcask:put(Handle, {thing, 3}, {this, is, data}).
bitcask:get(Handle, {thing, 3}).

然后出现一个新的 badarg 错误,其中包含 erlang:crc32 和我想要存储的值。

所以现在我使用这段代码,bucket是注册的gen_server的原子名称 使句柄保持在其状态。 cask_wrapper 是这些代码 gen_servers。下面的代码是对这些gen服务器的访问。

-module(sr_db).
...
get(Type, Key) when not is_binary(Key) ->
    ?MODULE:get(Type, term_to_binary(Key));
get(Type, Key) ->
    Bucket = type2bucket(Type),
    cask_wrapper:get(Bucket, {get, Key}).

put(Type, Key, Data) when not is_binary(Key) ->
    ?MODULE:put(Type, term_to_binary(Key), Data);

put(Type, Key, Data) when not is_binary(Data) ->
    ?MODULE:put(Type, Key, term_to_binary(Data));

put(Type, Key, Data) ->
    Bucket = type2bucket(Type),
    cask_wrapper:put(Bucket, Key, Data),
    ok.
%% syncput(Type, Key, Data) -> call au lieu de cast

type2bucket(user) -> users_cask.

我使用这样的代码:

sr_db:get(user, 3).
%% then a call is made to cask_wrapper:get(users_cask, {get, 3}).

有 cask_wrapper 函数,

get(Bucket, Key) ->
    gen_server:call(Bucket, {get, Key}).

handle_call({get, Key}, _From, State) ->
    Fetch = bitcask:get(State#state.handle, Key),
    {reply, Fetch, State}.

我使用与 put 函数相同的机制。 (但使用 gen_server:cast)

我的第一个问题是:在每次调用中都进行 term_to_binary 转换 一个很好的做法,还是很慢?我将不得不转换回 erlang 术语我获取的值。

此时,put 操作返回“ok”。有用。但得到 操作还不能进行。这就是错误:

=ERROR REPORT==== 29-Jan-2012::20:21:24 ===
** Generic server users_cask terminating
** Last message in was {get,{get,<<131,97,3>>}}
** When Server state == {state,#Ref<0.0.0.353>}
** Reason for termination ==
** {badarg,[{bitcask_nifs,keydir_get_int,[<<>>,{get,<<131,97,3>>}]},
            {bitcask_nifs,keydir_get,2},
            {bitcask,get,3},
            {cask_wrapper,handle_call,3},
            {gen_server,handle_msg,5},
            {proc_lib,init_p_do_apply,3}]}
Bitcask dir : "/home/niahoo/src/skyraiders/priv/bitcasks/users"
options : [read_write]** exception exit: {{badarg,
                        [{bitcask_nifs,keydir_get_int,
                             [<<>>,{get,<<131,97,3>>}]},
                         {bitcask_nifs,keydir_get,2},
                         {bitcask,get,3},
                         {cask_wrapper,handle_call,3},
                         {gen_server,handle_msg,5},
                         {proc_lib,init_p_do_apply,3}]},
                    {gen_server,call,[users_cask,{get,{get,<<131,97,3>>}}]}}
     in function  gen_server:call/2

我不明白为什么它不起作用,希望得到一些帮助。

谢谢

(edit: i miss some reputation to create the bitcask tag so ...)

(tl;dr => bitcask:get/2 doesn't work and raises badarg in bitcask_nifs:keydir_get_int)

I would like to know how to use bitcask without riak the right way.

First, i was trying this:

bitcask:put(Handle, 3, {this, is, data}).
bitcask:get(Handle, 3).

This two calls raise the same error : badarg with erlang:size/1

The problem is erlang:size/1 accepts only binaries or tuples.
So i was trying this :

bitcask:put(Handle, {thing, 3}, {this, is, data}).
bitcask:get(Handle, {thing, 3}).

A new badarg error then, with erlang:crc32 and the Value i want to store.

So now i use this code, bucket is the atom name of a registered gen_server
which keeps the handle in its state. cask_wrapper is the code for theese
gen_servers. The code below is the acces to theese gen servers.

-module(sr_db).
...
get(Type, Key) when not is_binary(Key) ->
    ?MODULE:get(Type, term_to_binary(Key));
get(Type, Key) ->
    Bucket = type2bucket(Type),
    cask_wrapper:get(Bucket, {get, Key}).

put(Type, Key, Data) when not is_binary(Key) ->
    ?MODULE:put(Type, term_to_binary(Key), Data);

put(Type, Key, Data) when not is_binary(Data) ->
    ?MODULE:put(Type, Key, term_to_binary(Data));

put(Type, Key, Data) ->
    Bucket = type2bucket(Type),
    cask_wrapper:put(Bucket, Key, Data),
    ok.
%% syncput(Type, Key, Data) -> call au lieu de cast

type2bucket(user) -> users_cask.

I use this code like this:

sr_db:get(user, 3).
%% then a call is made to cask_wrapper:get(users_cask, {get, 3}).

there are the cask_wrapper functions

get(Bucket, Key) ->
    gen_server:call(Bucket, {get, Key}).

handle_call({get, Key}, _From, State) ->
    Fetch = bitcask:get(State#state.handle, Key),
    {reply, Fetch, State}.

I use the same mechanism with the put function. (but with gen_server:cast)

My first question is : is doing term_to_binary conversion in every call
a good practice, or is it slow ? I will have to convert back to erlang
terms the values that i fetch.

At the moment, the put operation returns 'ok'. It works. But the get
operation doesn't work yet. This is the error:

=ERROR REPORT==== 29-Jan-2012::20:21:24 ===
** Generic server users_cask terminating
** Last message in was {get,{get,<<131,97,3>>}}
** When Server state == {state,#Ref<0.0.0.353>}
** Reason for termination ==
** {badarg,[{bitcask_nifs,keydir_get_int,[<<>>,{get,<<131,97,3>>}]},
            {bitcask_nifs,keydir_get,2},
            {bitcask,get,3},
            {cask_wrapper,handle_call,3},
            {gen_server,handle_msg,5},
            {proc_lib,init_p_do_apply,3}]}
Bitcask dir : "/home/niahoo/src/skyraiders/priv/bitcasks/users"
options : [read_write]** exception exit: {{badarg,
                        [{bitcask_nifs,keydir_get_int,
                             [<<>>,{get,<<131,97,3>>}]},
                         {bitcask_nifs,keydir_get,2},
                         {bitcask,get,3},
                         {cask_wrapper,handle_call,3},
                         {gen_server,handle_msg,5},
                         {proc_lib,init_p_do_apply,3}]},
                    {gen_server,call,[users_cask,{get,{get,<<131,97,3>>}}]}}
     in function  gen_server:call/2

I can't figure out why it does not work and would appreciate some help.

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

软糯酥胸 2025-01-05 09:49:05

Bitcask 期望键和值都是二进制文件(正如您已经注意到的那样)。
我真的不知道 term_to_binary/binary_to_term 有多快,但是如果您想在磁盘上存储术语,确实没有办法解决它。您当然可以编写自己的代码来将键和值转换为二进制文件或从二进制文件转换为键和值,但我怀疑它会比内置函数快得多,而且肯定不太灵活。
但最终您必须衡量应用程序的配置文件,并确定 term_to_binary/binary_to_term 是否是整个系统中的热点。如果在任何需要将数据写入磁盘的实际应用程序中都是这种情况,我会感到非常惊讶。

现在来看看调用 sr_db:get/2 时的错误。您将密钥包装在 {get, Key} 元组中两次,一次包装在 sr_db:get/2 中,另一次包装在 cask_wrapper:get/2 中,但通过匹配 cask_wrapper:handle_call/3 只将其解开一次。
您可以立即在错误报告中的这两行中发现这一点:

** 最后一条消息是 {get,{get,<<131,97,3>>}}

并且

{gen_server,call,[users_cask,{get,{get,<<131,97,3>>}}]}}

Bitcask expects the key and the value both to be binaries (as you already noticed).
I don't really know how fast term_to_binary/binary_to_term is, but there is really no way around it if you want to store terms on disk. You could of course roll you own code to convert you keys and values to/from binaries, but I doubt that it will be significantly fast than the builtin functions and certainly less flexible.
But at the end of the day you have to measure the profile your application, and decide if term_to_binary/binary_to_term is a hotspot in your total system. I would be very surprised if that is the case in any real application where data has to be written to disk.

Now to the error when calling sr_db:get/2. You are wrapping the key twice inside a {get, Key} tuple, once inside sr_db:get/2 and another time in cask_wrapper:get/2, but you unwrap it only once, by matching in cask_wrapper:handle_call/3.
You can immediately spot this in the error report in those two lines:

** Last message in was {get,{get,<<131,97,3>>}}

and

{gen_server,call,[users_cask,{get,{get,<<131,97,3>>}}]}}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文