【问题标题】:How to use bitcask as a stand alone如何单独使用 bitcask
【发布时间】:2012-01-31 19:33:20
【问题描述】:

(编辑:我想念一些创建 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。下面的代码是这些代服务器的访问权限。

-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

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

谢谢

【问题讨论】:

    标签: erlang riak


    【解决方案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,>}}

    {gen_server,call,[users_cask,{get,{get,>}}]}}

    【讨论】:

    • aaaaarf 这是一个愚蠢的复制粘贴错误 :) 非常感谢你。关于二进制转换,我认为 bitcask 提供了他自己的处理方式。所以我会坚持我的代码,稍后再介绍一下。谢谢。
    猜你喜欢
    • 2012-03-10
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    • 2020-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多