原文链接

批量操作优化:

  • 在使用redis的时候,客户端通过socket向redis服务端发起请求后,等待服务端的返回结果。
  • 客户端请求服务器一次就发送一个报文 -> 等待服务端的返回 -> 关闭连接
  • 如果是100个请求、1000个请求,那就得请求100次、1000次
  • 所以使用多个请求的时候使用管道来操作(如果管道打包的命令太多占用的内存也会越大,适量)
  • 以下是使用3种方式进行的测试(循环写入1000次):

    public static void main(String[] args) {
    
        long start = System.currentTimeMillis();
    for (int i = 0; i < 1000; i++) {
    template.opsForHash().put("user1", "status" + i, "value" + i);
    }
    System.out.println(System.currentTimeMillis() - start); start = System.currentTimeMillis();
    final byte[] rawKey = rawKey("user2");
    template.execute(new RedisCallback<Object>() { @Override
    public Object doInRedis(RedisConnection connection)
    throws DataAccessException {
    for (int i = 0; i < 1000; i++) {
    final byte[] rawHashKey = rawHashKey("status" + i);
    final byte[] rawHashValue = rawHashValue("value" + i); connection.hSet(rawKey, rawHashKey, rawHashValue);
    }
    return null;
    }
    });
    System.out.println(System.currentTimeMillis() - start); start = System.currentTimeMillis();
    final byte[] rawKey2 = rawKey("user3");
    template.execute(new RedisCallback<Object>() { @Override
    public Object doInRedis(RedisConnection connection)
    throws DataAccessException {
    connection.openPipeline();
    for (int i = 0; i < 1000; i++) {
    final byte[] rawHashKey = rawHashKey("status" + i);
    final byte[] rawHashValue = rawHashValue("value" + i); connection.hSet(rawKey2, rawHashKey, rawHashValue);
    }
    return connection.closePipeline();
    }
    });
    System.out.println(System.currentTimeMillis() - start);
    }
  • 请求结果

    20:54:51.653 [main] DEBUG o.s.d.r.core.RedisConnectionUtils - Opening RedisConnection
    20:54:51.693 [main] DEBUG o.s.d.r.core.RedisConnectionUtils - Closing Redis Connection
    42283
    20:54:51.695 [main] DEBUG o.s.d.r.core.RedisConnectionUtils - Opening RedisConnection
    20:55:33.922 [main] DEBUG o.s.d.r.core.RedisConnectionUtils - Closing Redis Connection
    42228
    20:55:33.923 [main] DEBUG o.s.d.r.core.RedisConnectionUtils - Opening RedisConnection
    20:55:34.058 [main] DEBUG o.s.d.r.core.RedisConnectionUtils - Closing Redis Connection
    136
  • 可以看出在使用管道打包发送请求所用的时间不到1s。而发送1000次请求所用的时间达到了42s。

从请求结果看到多次 Opening RedisConnection 和 Closing Redis Connection 的日志.

阅读源代码我们可以发现我们对redis的所有操作都是通过回调execute函数执行的,其代码如下:

public <T> T execute(RedisCallback<T> action, boolean exposeConnection) {
return execute(action, exposeConnection, false);
}
// execute实现如下:
// org.springframework.data.redis.core.RedisTemplate<K, V> --- 最终实现
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, boolean pipeline) {
Assert.isTrue(initialized, "template not initialized; call afterPropertiesSet() before using it");
Assert.notNull(action, "Callback object must not be null");
RedisConnectionFactory factory = getConnectionFactory();
RedisConnection conn = null;
try {
if (enableTransactionSupport) {
// only bind resources in case of potential transaction synchronization
conn = RedisConnectionUtils.bindConnection(factory, enableTransactionSupport);
} else {
conn = RedisConnectionUtils.getConnection(factory);
}
boolean existingConnection = TransactionSynchronizationManager.hasResource(factory);
RedisConnection connToUse = preProcessConnection(conn, existingConnection);
boolean pipelineStatus = connToUse.isPipelined();
if (pipeline && !pipelineStatus) {
connToUse.openPipeline();
}
RedisConnection connToExpose = (exposeConnection ? connToUse : createRedisConnectionProxy(connToUse));
T result = action.doInRedis(connToExpose);
// close pipeline
if (pipeline && !pipelineStatus) {
connToUse.closePipeline();
}
// TODO: any other connection processing?
return postProcessResult(result, connToUse, existingConnection);
} finally {
if (!enableTransactionSupport) {
RedisConnectionUtils.releaseConnection(conn, factory);
}
}
}

这里面每次执行action.doInRedis(connToExpose)前都要调用RedisConnectionUtils.getConnection(factory);获得一个连接,进入RedisConnnectionUtils类中,getConnection(factory)最终调用的是doGetConnection(factory, true, false, enableTranactionSupport)这个函数。这个函数我们可以看下api文档,发现实际上并不是真的创建一个新的redis连接,它只是在connectFactory中获取一个连接,也就是从连接池中取出一个连接。当然如果connectFactory没有连接可用,此时如果allowCreate=true便会创建出一个新的连接,并且加入到connectFactory中。

基本上可以确定真实的情况是spring-data-redis已经帮我们封装了连接池管理,我们只需要调用一系列操作函数即可,这给操作redis带来了极大的方便。

【转载】redis优化的更多相关文章

  1. Redis 优化查询性能

    一次使用 Redis 优化查询性能的实践   应用背景 有一个应用需要上传一组ID到服务器来查询这些ID所对应的数据,数据库中存储的数据量是7千万,每次上传的ID数量一般都是几百至上千数量级别. 以前 ...

  2. 一次使用 Redis 优化查询性能的实践

    因为我的个人网站 restran.net 已经启用,博客园的内容已经不再更新.请访问我的个人网站获取这篇文章的最新内容,一次使用 Redis 优化查询性能的实践 应用背景 有一个应用需要上传一组ID到 ...

  3. [转载]机器学习优化方法总结:SGD,Momentum,AdaGrad,RMSProp,Adam

    [转载]机器学习优化方法总结:SGD,Momentum,AdaGrad,RMSProp,Adam https://blog.csdn.net/u010089444/article/details/76 ...

  4. 【转载】Redis优化经验

    转载地址:http://blog.sina.com.cn/s/blog_4be888450100z2ze.html 内存管理优化 Redis Hash是value内部为一个HashMap,如果该Map ...

  5. 【转载】redis优化配置和redis.conf说明

    转载地址:http://blog.csdn.net/luozhonghua2014/article/details/40568707?utm_source=tuicool&utm_medium ...

  6. [转载] Redis

    转载:http://snowolf.iteye.com/blog/1630697 大约一年多前,公司同事开始使用Redis,不清楚是配置,还是版本的问题,当时的Redis经常在使用一段时间后,连接爆满 ...

  7. [转载] Redis 起步

    转载地址:http://www.cnblogs.com/shanyou/archive/2012/01/28/2330451.html Rdis和JQuery一样是纯粹为应用而产生的,这里记录的是在C ...

  8. [转载] Redis资料汇总专题

    转载自http://www.cnblogs.com/tommyli/archive/2011/12/14/2287614.html 1.Redis是什么? 十五分钟介绍 Redis数据结构 Redis ...

  9. Redis优化之CPU充分利用

    Linux Redis Server之CPU充分利用 不知道大家有没有注意到你们公司的集群配置是否是有一种配置是这样的: 多个Redis Server分布在同一个节点,只是端口不同,如果有的话,应该是 ...

随机推荐

  1. 折腾deeplin系统

    1.双系统失败记录 多系统启动问题 先安装完deepin,发现再安装windows怎么都起不起来,哪怕他们已经安装在不同的盘 (体现再Windows7通过ghost位于另外一个盘,但就是没有启动项) ...

  2. org.apache.hadoop.yarn.exceptions.InvalidAuxServiceException: The auxService: mapreduce_shuffle do

    在yarn-site.xml 配置文件中增加: <property> <name>yarn.nodemanager.aux-services</name> < ...

  3. 【BZOJ4872】[Shoi2017]分手是祝愿 数学+期望DP

    [BZOJ4872][Shoi2017]分手是祝愿 Description Zeit und Raum trennen dich und mich. 时空将你我分开.B 君在玩一个游戏,这个游戏由 n ...

  4. Maven开发系统

    Maven的优点: 自动从互联网中获取jar包,并实现了一步构建. pom.xml的配置 依赖管理(导入对应的jar包) 通过坐标(定位到仓库中的包的位置,并将jar包导入到项目中,如果版本升级,只需 ...

  5. LAMP集群项目五 nfs存储的数据实时同步到backupserver

    tar fxzsersync2.5.4_64bit_binary_stable_final.tar.gz -C /usr/local/ mv GNU-Linux-x86 sersync cp sers ...

  6. log4j日志服务器配置

    可参考的文章: http://www.jb51.net/article/89597.htm http://www.jb51.net/article/41001.htm http://liuzhijun ...

  7. 阿里云服务器Mysql修改密码

    核心架构基于阿里云服务器CentOS7.2操作系统,全面支持Java Web运行环境   Tomcat 8.5.8 JDK 8u111 MySQL5.7.16 详细信息,请在服务器执行  more r ...

  8. HDU1811 拓扑排序判环+并查集

    HDU Rank of Tetris 题目:http://acm.hdu.edu.cn/showproblem.php?pid=1811 题意:中文问题就不解释题意了. 这道题其实就是一个拓扑排序判圈 ...

  9. Static Import Constant interface

    Static Import https://docs.oracle.com/javase/1.5.0/docs/guide/language/static-import.html In order t ...

  10. MySQL给一个字段递增赋值

    https://blog.csdn.net/kriszhang/article/details/72125203 首先设置一个变量,初始值为0: set @r:=0; 1 然后更新表中对应的ID列: ...