我对埃尔朗还不熟悉,这是一次冒险。我想实现一个速率限制器,并遇到了一些与密钥生成有关的问题。不久前,我已经修改了限制器的实现…大概一年吧。我想清理一下…
(这是一个大得多的项目中的一小部分。现在我要认真对待)
我只能想象我的应用程序是成功的,我每秒收到数万个请求。当我第一次编写代码时,这里有一个片段:

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是否能存储二进制数据。我做了一些调查,答案是(应该是)是的……在程序上,作为键和值。所以我在贝壳里试了一下:
eredis:q(R,["set",R,R]).

r被扩展成27字节的二进制文件,但失败了。然后,我将其他字节分配给两个变量并插入它们…同样的结果。
我刚开始重写我在爱尔兰的限制器:
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是要存储的键/值,表示为io_list(列表和二进制文件的嵌套列表)。
我不明白你到底想存储什么,假设你想为每个客户存储2张记录,一张是时间记录,一张是时间记录。你可以通过代码来实现这一点:

{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)]),

或者如果您想要一个单独的记录:
eredis:q(Pid,["set",term_to_binary(ClientIP),term_to_binary([Time,TimeLong])]),

09-11 20:08