如何单独使用bitcask

时间:2012-01-29 19:27:56

标签: erlang riak

(编辑:我错过了创建bitcask标签的声誉......)

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

我想知道如何以正确的方式使用没有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是theese的代码 gen_servers。下面的代码是对theese 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

我无法弄清楚为什么它不起作用,并希望得到一些帮助。

谢谢

1 个答案:

答案 0 :(得分: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,&lt;&lt; 131,97,3&gt;&gt;}}}

  

{gen_server,呼叫,[users_cask,{得到,{获得,&LT;&LT; 131,97,3&GT;&GT;}}]}}