本文环境: jedis 2.1.0
redis 2.8.13
我们的各个子系统均使用jedis作为redis的java client读写数据。
jedis底层使用apache的common pool,每个jedis对象在底层都视为一个object。
当释放连接失败后,我们的做法只是输出错误日志,这会导致该连接无法回收再利用,最终服务器的连接池会被拖垮,现象就是我们遇到的无响应、重启就好。
此前我们分析过,现在得出的结论是:这不是服务器操作系统连接数的问题,也不是数据频繁读写的问题,而是释放资源时遇到异常时,我们没有将该连接直接断掉、丢弃。
如下是aenv代码的相关变更情况,仅做参考:
常用的jedis读写方式包括:set/get、hset/hget和mset/mget,分别用作基本读写、hash读写和批量读写。
对此,我进行了一次性能测试(见下图)。
从结果上看,批量读写的优势是非常明显的,如果子系统有类似业务逻辑,希望考虑这种形式。对于hash读写,在数据量聚集在某个特殊范围内时,其效率是比基本读写要高的。
另外,jedis的单点是线程不安全的,通过apache的common pool获取的jedis实例是线程安全的,因此不建议子系统使用new一个实例的方式。
本次调研的目的是:观察主从复制、读写分离是否可以提高读写效率(虽然主从模式会提供高可用性,但目前子系统更关注的是速度)。
测试采用两个jedis线程池一主一辅,主写、辅读。
单线程的测试结果如读写性能并不高。
100个线程的测试情况如下。从图中可以看出,数据量增到10000条的时候是个拐点,读写分离在此处开始呈现优势。不管是否读写分离,单次set永远不是高效的写入方式。
hset在5万条数据的单机读写时出现过读超时,怀疑在做rehash(表中红色条目)。
附:
docker redis示意图:
![2014_08_27_redis_master_slave]