1

(编辑:我想念一些创建 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 with 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”。有用。但是get操作还不行。这是错误:

=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

我不知道为什么它不起作用,希望能得到一些帮助。

谢谢

4

1 回答 1

1

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>>}}]}}

于 2012-01-31T11:33:20.000 回答