【转载】redis优化

原文链接

批量操作优化:

  • 在使用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带来了极大的方便。

原文地址:https://www.cnblogs.com/mr-yang-localhost/p/8461289.html

时间: 2024-10-08 04:44:12

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

Redis优化高并发下的秒杀性能

本文内容 使用Redis优化高并发场景下的接口性能数据库乐观锁 随着双12的临近,各种促销活动开始变得热门起来,比较主流的有秒杀.抢优惠券.拼团等等.涉及到高并发争抢同一个资源的主要场景有秒杀和抢优惠券. 前提 活动规则 奖品数量有限,比如100个 不限制参与用户数 每个用户只能参与1次秒杀 活动要求 不能多发,也不能少发,100个奖品要全部发出去 1个用户最多抢1个奖品 遵循先到先得原则,先来的用户有奖品 数据库实现 悲观锁性能太差,本文不予讨论,讨论一下使用乐观锁解决高并发问题的优缺点.数据

一文带你了解Redis优化高并发下的秒杀性能

本文内容 使用Redis优化高并发场景下的接口性能数据库乐观锁 随着双12的临近,各种促销活动开始变得热门起来,比较主流的有秒杀.抢优惠券.拼团等等.涉及到高并发争抢同一个资源的主要场景有秒杀和抢优惠券. 前提 活动规则 奖品数量有限,比如100个 不限制参与用户数 每个用户只能参与1次秒杀 活动要求 不能多发,也不能少发,100个奖品要全部发出去 1个用户最多抢1个奖品 遵循先到先得原则,先来的用户有奖品 数据库实现 悲观锁性能太差,本文不予讨论,讨论一下使用乐观锁解决高并发问题的优缺点.数据

[转载] Redis

转载:http://snowolf.iteye.com/blog/1630697 大约一年多前,公司同事开始使用Redis,不清楚是配置,还是版本的问题,当时的Redis经常在使用一段时间后,连接爆满且不释放.印象中,Redis 2.4.8以下的版本由于设计上的主从库同步问题,就会导致整个问题,不知是否确为这个Bug所致.但从那以后,我就很少敢去尝试使用Redis.曾想转投MongoDB,但公司同事给我的回复是,由于MongoDB宕机,数据丢失,公司损失惨重.于是,我一直停留在Memcached

[转载] Redis 起步

转载地址:http://www.cnblogs.com/shanyou/archive/2012/01/28/2330451.html Rdis和JQuery一样是纯粹为应用而产生的,这里记录的是在CentOS 5.7上学习入门文章: 1.Redis简介 Redis是一个key-value存储系统.和Memcached类似,但是解决了断电后数据完全丢失的情况,而且她支持更多无化的value类型,除了和string外,还支持lists(链表).sets(集合)和zsets(有序集合)几种数据类型.

[转载] Redis资料汇总专题

转载自http://www.cnblogs.com/tommyli/archive/2011/12/14/2287614.html 1.Redis是什么? 十五分钟介绍 Redis数据结构 Redis系统性介绍 一个很棒的Redis介绍PPT 强烈推荐!非同一般的Redis介绍 Redis之七种武器 锋利的Redis redis 适用场景与实现 2.Redis内部实现 Redis源码分析系列文章 深入Redis内部-Redis 源码讲解 redis源码分析-如何rehash Redis源码分析-

[转载] redis 的两种持久化方式及原理

转载自http://www.m690.com/archives/371 Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服务器端计算集合的并,交和补集(difference)等,还支持多种排序功能.所以Redis也可以被看成是一个数据结构服务器.Redis的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”):也可以把每一次数据变化都写入到一个app

Redis优化经验

内存管理优化 Redis Hash是value内部为一个HashMap,如果该Map的成员数比较少,则会采用类似一维线性的紧凑格式来存储该Map, 即省去了大量指针的内存开销,这个参数控制对应在redis.conf配置文件中下面2项: hash-max-zipmap-entries 64 hash-max-zipmap-value 512 当value这个Map内部不超过多少个成员时会采用线性紧凑格式存储,默认是64,即value内部有64个以下的成员就是使用线性紧凑存储,超过该值自动转成真正的

[转载]页面优化——网页优化

前端是庞大的,包括HTML.CSS.Javascript.Image.Flash等等各种各样的资源.前端优化是复杂的,针对方方面面的资源都有不同的方式.那么,前端优化的目的是什么 1. 从用户角度而言,优化能够让页面加载得更快.对用户的操作响应得更及时,能够给用户提供更为友好的体验. 2. 从服务商角度而言,优化能够减少页面请求数.或者减小请求所占带宽,能够节省可观的资源. 总之,恰当的优化不仅能够改善站点的用户体验并且能够节省相当的资源利用. 前端优化的途径有很多,按粒度大致可以分为两类,第一

redis优化秒杀系统

用redis提高基于mss的秒杀系统 使用背景: 普通的基于mss框架的系统在并发量不是很高的情况下,对redis的需求不是很高.redis在系统中的角色相当于一个对象缓存器,在高并发的系统中(比如秒杀系统),在某一刻对数据库中的一条数据可能是成千上万的用户同时去访问,系统的用户体验度直接受到数据库的性能的影响.为了保证数据的完整性,用户只能串行访问数据库中的某一条记录.redis则是把记录对应的对象序列化存储在自身的容器中,减少数据库的压力.废话不多说,接下来简单介绍redis的使用. red