10

我对应该如何使用胭脂红进行通话感到困惑。我发现了胭脂红文档wcar中描述的宏:

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

除了redis命令之外,我真的wcar每次想和redis通话时都要打电话吗?或者我可以在一开始就调用一次吗?如果有怎么办?

这是 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")))))

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

4

2 回答 2

9

丹的解释是正确的。

Carmine默认情况下使用响应流水线,而redis-clojure需要您在需要时请求流水线(使用pipeline宏)。

你想要流水线的主要原因是为了性能。Redis 是如此之快,以至于使用它的瓶颈通常是请求+响应通过网络传输所需的时间。

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

(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 将响应排队,然后将它们作为我们将解构的向量一次性接收。

起初,这似乎是不必要的额外工作,因为它要求您明确何时接收排队响应,但它带来了很多好处,包括性能、清晰度和可组合的命令

如果您正在寻找我认为惯用Carmine用法的示例(只需搜索wcar调用),我会在 GitHub 上查看 Touchstone。(对不起,所以阻止我包含另一个链接)。

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

于 2013-01-16T08:09:18.797 回答
6

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

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

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

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

wcar那么,现在的问题是,当 Redis-Clojure 只需要一个 时,为什么 Carmine 需要多个's with-server

答案是,它没有。除了有时,当它发生时。Carminewith-conn使用 Redis 的“流水线”以相同的连接发送多个请求,然后将响应打包在一个向量中。自述文件中的示例显示了这一点。

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

在这里您会看到pingset并且get只关心发送请求,而将接收响应留给wcar。这排除了 wcar 内部的断言(或任何结果访问),并导致wcar您拥有的请求和多个调用分离。

于 2013-01-13T01:58:46.427 回答