调研
从redis官网推荐、hex.pm下载中可以看到。有 redix/eredis 供选择。
redix vs eredis
redix 在如下方面有明显的优势:
- redix支持链接多路复用。而eredis是poolboy,一个链接同一时间只能阻塞执行一条指令。
- 支持child_spec,后台静默重连,用gen_statem处理重连期间的请求,大部分时候重连无感。
telemetry,监控、日志通过注册回调的方式接入。
上述差异让 redix 在性能、鲁棒性、接入难度上有明显的优势。redis cluster
目前 elixir erlang 没有产品级的 redis cluster driver 实现。
eredis_cluster 和 nebulex_redis_adapter 类似。通过 CLUSTER SLOTS/ CLUSTER SHARDS 指令拉取集群节点。并通过CRC16算法并对槽位取余,遇到 MOVED 错误返回,则刷新槽位信息。
有个核心问题没有被解决:transaction 需要在多个节点上执行,如何保证原子性?可以直接使用阿里云redis,不需要关心 redis 集群迁移。从工程角度来说,提供一个高性能的redis router,供不同语言使用,是综合成本更小,性能更好的方案。eredis_cluster
- 不支持多节点 transaction。
- 需要自己判断是否多节点指令,区分使用 q/qmn 接口。
会对 key 做 binary_to_list 再执行crc算法。
:eredis_cluster.start() :eredis_cluster.connect([{'127.0.0.1', 6379}], [ {:pool_size, @pool_size}, {:pool_max_overflow, 0} ]) {:ok, _} = :eredis_cluster.q(["SET", "K", "V"])
nebulex_redis_adapter
nebulex_redis_adapter 准确来说不算是 redis cluster 的封装,作者的意图是隐藏底层的差异,提供一个分布式的get/set cache。其 redis_cluster 模式,压根没有处理核心的路由问题,需要用户自己传入key。
- 需要自行传入key,不支持多节点 pipeline,transaction。
- 哈希计算之前,如果不是binary会调用 serialize 逻辑,默认的逻辑会因为 term_to_binary 导致 slot 计算不正确。
需要用户指定模式 standalone(单点)/redis_cluster(redis集群,服务端指定槽位)/client_side_cluster(客户端指定槽位并哈希,显然不可横向拓展)。
redis_cluster模式示例:defmodule MyApp.RedisClusterCache do use Nebulex.Cache, otp_app: :nebulex, adapter: NebulexRedisAdapter end opts = [ name: :test, mode: :redis_cluster, redis_cluster: [ configuration_endpoints: [ endpoint1: [ host: "127.0.0.1", port: 7000 ] ] ] ] child = MyApp.RedisClusterCache.child_spec(opts) Supervisor.start_link(children, opts) {:ok, ["OK"]} = MyApp.RedisClusterCache.pipeline([["SET", "K", "V"]], name: :redix_cluster, key: "K")
结论
我们只需要封装redis standalone模式:https://github.com/enjolras1205/redix_pool
参考
- https://redis.io/resources/clients/#elixir
- https://hex.pm/packages?search=redis&sort=recent_downloads
- https://severalnines.com/blog/hash-slot-vs-consistent-hashing...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。