Below you will find pages that utilize the taxonomy term “编程小记”
Posts
编程小记: bug、clojure 状态和 paxos
一个 Bug 前段时间观察我们 API 系统的 hystrix 监控,一直发现一个函数 cache/add 的调用特别的高,在整个集群范围内高峰的时候接近 3 到 4 万的 QPS,跟其他指标比起来非常的碍眼,极不正常。
抽了点时间专门调查了下,原来是不小心掉进去了 hystrix request cache 的坑里。
Hystrix Request Cache 的原理很简单,在同一个 RequestContext 里,对某个 command 调用同样的参数,第一次调用的结果将被缓存,后续的对同样参数的请求将直接返回第一次的结果,通过内存换效率,类似 clojure 的 memoize。
简单例子:
(require '[com.netflix.hystrix.core :refer [defcommand with-request-context]])) (def call-times (atom 0)) (defcommand myinc {:hystrix/cache-key-fn (fn [i] (str i))} [i] (swap! call-times inc) ;;统计调用次数 (+ 1 i)) (with-request-context ;;调用了两次 myinc (myinc 1) (myinc 1)) (println @call-times) ;; call-times 只统计了一次调用。 业务代码里有一段逻辑大概是这样:
(def get-or-create [k nv] (if-let [v (get-value k)] v (if-not (add k nv) (recur k nv) nv))) 其中 get-value 是一个 hystrix command 设置了 cache-fn 启用了请求缓存。这段代码是尝试先从缓存里加载 k 对应的值,如果没有,就将 nv 存储到 k 键上,如果 add 存储成功,返回 nv,如果 add 失败,循环重试(表示有其他人 add 成功,我们可以重试 get-value)。