Erlang:如何在 eredis 中使用二进制密钥/数据?
Erlang: How can I use binary keys / data with eredis?
我对 erlang 有点陌生,这是一次冒险。我想实现一个速率限制器,但遇到了一些密钥生成问题。不久前我曾尝试实施限制器……大概一年。我想稍微清理一下...
(这是一个更大的项目中的一小部分。现在我正在认真对待它)
我只是想象我的应用程序是成功的,并且我每秒收到数万个请求。当我第一次编写代码时,这里有一个片段:
getClientIP(Socket) ->
{ok, {ClientIP, _ }} = inet:peername(Socket),
TplC = tuple_to_list(ClientIP),
{iolist_to_binary(TplC), lists:flatten(io_lib:format("~p",[TplC]))}.
makeRedisRLKeys(ClientIPStr,TimeShort,TimeLong) ->
RKeyPrefix = ClientIPStr ++ ":",
{ClientIPStr, RKeyPrefix ++ integer_to_list(TimeShort) ++ ":16s", RKeyPrefix ++ integer_to_list(TimeLong) ++ ":36h"}.
所有这些代码... 运行 一遍又一遍。我很好奇redis是否可以存储二进制数据。我做了一些搜索,答案是(应该是)是的......以编程方式作为键和值。所以我在 shell 中尝试了它:
eredis:q(R,["set",R,R]).
R 已扩展为 27 字节二进制文件,但失败了。然后我将杂项字节分配给两个变量并插入它们......结果相同。
我刚开始在 erlang 端重写我的限制器:
rate_limit(PartialKey) ->
{ M, S, _ } = now(),
Time = M*1000000 + S,
TimeLong = Time band 16#fffffffffffff000,
我知道下面的内容在语法上不正确,但我正在尝试做类似的事情:
BucketShort = <<ClientIP, Time>>,
BucketLong = <<ClientIP, TimeLong>>,
可能吗?
eredis 查询的语法很奇怪:eredis:q(R,["set",R,R])
。除非 R 是您的 eredis 应用程序的 pid,否则将失败。
"set" 命令的语法是 eredis:q(Pid,["set",Key,Value]).
其中 Pid 是 eredis 应用程序的 pid: {ok, Pid} = eredis:start_link()
, Key 和 Value 是你想要的 key/value存储表示为 io_list(列表和二进制文件的嵌套列表)。
我不明白你到底想存储什么,假设你想为每个 ClientIP 存储 2 条记录,一条是 Time,一条是 TimeLong。您可以使用以下代码实现此目的:
{ok, Pid} = eredis:start_link(),
eredis:q(Pid,["set",term_to_binary([ClientIP,short]),term_to_binary(Time)]),
eredis:q(Pid,["set",term_to_binary([ClientIP,long]),term_to_binary(TimeLong)]),
或者如果您想要 1 条记录:
eredis:q(Pid,["set",term_to_binary(ClientIP),term_to_binary([Time,TimeLong])]),
我对 erlang 有点陌生,这是一次冒险。我想实现一个速率限制器,但遇到了一些密钥生成问题。不久前我曾尝试实施限制器……大概一年。我想稍微清理一下...
(这是一个更大的项目中的一小部分。现在我正在认真对待它)
我只是想象我的应用程序是成功的,并且我每秒收到数万个请求。当我第一次编写代码时,这里有一个片段:
getClientIP(Socket) ->
{ok, {ClientIP, _ }} = inet:peername(Socket),
TplC = tuple_to_list(ClientIP),
{iolist_to_binary(TplC), lists:flatten(io_lib:format("~p",[TplC]))}.
makeRedisRLKeys(ClientIPStr,TimeShort,TimeLong) ->
RKeyPrefix = ClientIPStr ++ ":",
{ClientIPStr, RKeyPrefix ++ integer_to_list(TimeShort) ++ ":16s", RKeyPrefix ++ integer_to_list(TimeLong) ++ ":36h"}.
所有这些代码... 运行 一遍又一遍。我很好奇redis是否可以存储二进制数据。我做了一些搜索,答案是(应该是)是的......以编程方式作为键和值。所以我在 shell 中尝试了它:
eredis:q(R,["set",R,R]).
R 已扩展为 27 字节二进制文件,但失败了。然后我将杂项字节分配给两个变量并插入它们......结果相同。
我刚开始在 erlang 端重写我的限制器:
rate_limit(PartialKey) ->
{ M, S, _ } = now(),
Time = M*1000000 + S,
TimeLong = Time band 16#fffffffffffff000,
我知道下面的内容在语法上不正确,但我正在尝试做类似的事情:
BucketShort = <<ClientIP, Time>>,
BucketLong = <<ClientIP, TimeLong>>,
可能吗?
eredis 查询的语法很奇怪:eredis:q(R,["set",R,R])
。除非 R 是您的 eredis 应用程序的 pid,否则将失败。
"set" 命令的语法是 eredis:q(Pid,["set",Key,Value]).
其中 Pid 是 eredis 应用程序的 pid: {ok, Pid} = eredis:start_link()
, Key 和 Value 是你想要的 key/value存储表示为 io_list(列表和二进制文件的嵌套列表)。
我不明白你到底想存储什么,假设你想为每个 ClientIP 存储 2 条记录,一条是 Time,一条是 TimeLong。您可以使用以下代码实现此目的:
{ok, Pid} = eredis:start_link(),
eredis:q(Pid,["set",term_to_binary([ClientIP,short]),term_to_binary(Time)]),
eredis:q(Pid,["set",term_to_binary([ClientIP,long]),term_to_binary(TimeLong)]),
或者如果您想要 1 条记录:
eredis:q(Pid,["set",term_to_binary(ClientIP),term_to_binary([Time,TimeLong])]),