如何使用胭脂红的wcar宏?

时间:2013-01-12 16:52:33

标签: clojure redis carmine

我对如何使用胭脂红进行调用感到困惑。我找到了carmine's docs中描述的wcar宏:

(defmacro wcar [& body] `(car/with-conn pool spec-server1 ~@body))

除了redis命令之外,每次我想与redis交谈时,是否真的需要调用wcar?或者我可以在开始时调用一次吗?如果是这样的话?

这是tavisrudd的redis库的一些代码看起来像(来自我的玩具url缩短项目的测试套件):

(deftest test_shorten_doesnt_exist_create_new_next 
  (redis/with-server test-server
    (redis/set "url_counter" 51)
    (shorten test-url)
    (is (= "1g" (redis/get (str "urls|" test-url))))
    (is (= test-url (redis/get "shorts|1g")))))

现在我只能通过这样编写来使用胭脂红:

(deftest test_shorten_doesnt_exist_create_new_next
  (wcar (car/set "url_counter" 51))
    (shorten test-url)
    (is (= "1g" (wcar (car/get (str "urls|" test-url)))))
    (is (= test-url (wcar (car/get "shorts|1g")))))

那么使用它的正确方法是什么?我没有得到什么基本概念?

2 个答案:

答案 0 :(得分:9)

丹的解释是正确的。

Carmine默认情况下使用响应管道,而redis-clojure则要求您在需要时请求管道传输(使用pipeline宏)。

您想要流水线操作的主要原因是性能。 Redis速度非常快,以至于使用它的瓶颈通常是请求+响应通过网络传输所需的时间。

Clojure destructuring提供了一种处理流水线响应的便捷方式,但它确实需要以不同的方式编写代码redis-clojure。我写你的例子的方式是这样的(我假设你的shorten fn有副作用,需要在GET s之前调用:

(deftest test_shorten_doesnt_exist_create_new_next
  (wcar (car/set "url_counter" 51))
  (shorten test-url)
  (let [[response1 response2] (wcar (car/get (str "urls|" test-url))
                                    (car/get "shorts|1g"))]
    (is (= "1g" response1))
    (is (= test-url response2))))

所以我们将第一个(SET)请求发送给Redis并等待回复(我不确定这是否真的有必要)。然后我们立即发送接下来的两个(GET)请求,允许Redis对响应进行排队,然后立即将它们全部作为我们将要构造的向量接收。

首先,这似乎是不必要的额外努力,因为它要求您明确何时接收排队响应,但它带来了很多好处,包括性能,清晰度和composable commands

如果您正在寻找我认为惯用Carmine使用的示例(只搜索wcar来电),我会在GitHub上查看Touchstone。 (对不起,SO阻止我包含其他链接。)

如果您有任何其他问题,请向我发送电子邮件(或提交GitHub问题)。

答案 1 :(得分:6)

不用担心,您已经以正确的方式使用它了。

Redis请求函数(例如您上面使用的get和set)都通过另一个函数send-request!路由,该函数依赖于动态绑定*context*来提供连接。尝试在没有该上下文的情况下调用任何这些Redis命令将失败,并且没有上下文"错误。 with-conn宏(在wcar中使用)设置该上下文并提供连接。

wcar宏只是with-conn周围的一个瘦包装器,假设您将对所有Redis请求使用相同的连接详细信息。

到目前为止,这与Tavis Rudd redis-clojure的工作方式非常相似。

所以,现在的问题是,当Redis-Clojure只需要一个wcar时,Carmine需要多个with-server

答案是,它没有。除了有时,它确实如此。 Carmine with-conn使用Redis的"Pipelining"发送具有相同连接的多个请求,然后将响应打包在一个向量中。 README中的示例显示了这一点。

(wcar (car/ping)
      (car/set "foo" "bar")
      (car/get "foo"))
=> ["PONG" "OK" "bar"]

在这里,您会看到pingsetget仅关注发送请求,接收响应最多为wcar。这会阻止来自wcar内部的断言(或任何结果访问),并导致请求与您拥有的多个wcar呼叫分离。