皮皮网

【怎么有效阅读源码】【PDF上传提取源码】【除夕祝福php源码】jedispool 源码

2024-11-20 07:18:57 来源:证券盘源码

1.连接池:别让连接池帮了倒忙
2.Jedis连接池究竟是何物?
3.到底如何在spring中使用redis
4.jedis 和 strpin-data-redis 哪一个好

jedispool 源码

连接池:别让连接池帮了倒忙

       连接池技术在业务项目中扮演着重要角色,尤其是在数据库连接池、Redis连接池和HTTP连接池的使用上。今天,我们将围绕连接池的结构、使用和配置,怎么有效阅读源码以及如何避免常见错误,来深入探讨这一话题。

       连接池的结构主要包括对外提供连接获取与归还接口的客户端使用,以及内部实现的连接建立、连接心跳保持、连接管理、空闲连接回收、连接可用性检测等功能。在业务项目中,数据库连接池、Redis连接池和HTTP连接池是PDF上传提取源码最常见的三种连接池。

       在使用第三方客户端SDK进行网络通信时,首先需要确认SDK是否基于连接池技术实现。TCP作为面向连接的基于字节流的协议,如果SDK没有使用连接池,而是直接建立TCP连接,将需要考虑每次连接的开销,并且在多线程环境下可能产生线程安全问题。因此,除夕祝福php源码识别SDK连接池的实现方式至关重要。

       以Jedis作为Redis操作最常见的库为例,分析其源码。Jedis类是连接池与连接分离的API,内部维护一个Socket连接,多线程环境下复用连接可能导致命令执行不完整或线程安全问题。使用连接池如JedisPool,可以实现线程安全的spring流程审批源码复用,避免这些问题。确保关闭连接池,最好通过shutdownhook在程序退出时释放资源。

       连接池的配置不是一成不变的。最大连接数的设置需要根据容量规划,过大或过小都会影响性能。通过实践和监控,可以有效调整参数,源码文件怎么执行满足性能需求同时避免资源浪费。连接池的正确使用方式包括复用连接和确保在程序退出前关闭连接池。

       总结来说,理解连接池的实现方式、正确使用姿势和合理配置参数是确保高效、稳定的连接管理的关键。连接池技术能够显著提升性能,减少资源浪费,因此正确应用连接池对于提高系统性能至关重要。

Jedis连接池究竟是何物?

       连接池是管理并回收资源的对象集合,以减少系统资源的创建和销毁开销,提升系统吞吐量,适用于创建/销毁资源耗时的场景。以Jedis为例,其底层使用的是GenericObjectPool作为连接池实现。业务从空闲连接队列获取连接,最长等待时间由maxWaitMillis决定。获取后,检查是否有效,关闭后再次放入空闲队列或销毁。连接池的参数如配置文件中详细列出,Spring-Data-Redis将参数进行收敛,用户主要配置参数较少,关键参数包括验证方法的启用和关闭。Jedis实例通过Spring-Data-Redis封装后,实现对连接池的管理,提供了BorrowObject方法获取连接和ReturnObject方法归还连接。其中BorrowObject方法可能从空闲队列获取或创建新连接,超过最大等待时间则抛出异常。ReturnObject方法负责归还连接并进行有效性验证。连接池还包括定期驱逐/保活机制、检查机制和抛弃机制,通过配置参数、源码分析和JMX工具实现连接状态监控和问题排查。了解连接池原理有助于提升资源管理效率,并在实际应用中根据业务需求优化配置。

到底如何在spring中使用redis

       1. Redis使用场景

       Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

       æˆ‘们都知道,在日常的应用中,数据库瓶颈是最容易出现的。数据量太大和频繁的查询,由于磁盘IO性能的局限性,导致项目的性能越来越低。

       è¿™æ—¶å€™ï¼ŒåŸºäºŽå†…存的缓存框架,就能解决我们很多问题。例如Memcache,Redis等。将一些频繁使用的数据放入缓存读取,大大降低了数据库的负担。提升了系统的性能。

       å…¶å®žï¼Œå¯¹äºŽhibernate的二级缓存,是同样的道理。利用内存高速的读写速度,来解决硬盘的瓶颈。

       2. 配置使用redis

       é¦–先,我们需要引入基本的jar包。maven中的基本引用如下:

       ã€€ã€€ã€€ã€€<dependency>

        <groupId>org.springframework.data</groupId>

        <artifactId>spring-data-redis</artifactId>

        <version>1.4.2.RELEASE</version>

        </dependency>

        <dependency>

        <groupId>redis.clients</groupId>

        <artifactId>jedis</artifactId>

        <version>2.6.2</version>

        </dependency>

       ç„¶åŽï¼Œåœ¨applicationContext中配置如下:

       <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">

        <property name="maxIdle" value="${ redis.maxIdle}" />

        <property name="maxTotal" value="${ redis.maxActive}" />

        <property name="maxWaitMillis" value="${ redis.maxWait}" />

        <property name="testOnBorrow" value="${ redis.testOnBorrow}" />

        </bean>

        <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="${ redis.host}" p:port="${ redis.port}" p:password="${ redis.pass}"

        p:pool-config-ref="poolConfig" />

        <bean id="stringSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>

        <!-- 开启事务,可以通过transcational注解控制 -->

        <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">

        <property name="connectionFactory" ref="connectionFactory" />

        <property name="keySerializer" ref="stringSerializer" />

        <property name="enableTransactionSupport" value="true" />

        </bean>

       å¯¹äºŽhibernate的配置可知,第一个poolconfig是对连接池的配置。包括最大连接数,队列数,存活时间,最大等待时间等等,还有一些额外的配置,请直接点击JedisPoolConfig类源码,进行查看。

       è¿™äº›é…ç½®çš„意思如果不明白的话,一定要去把线程池好好学习下。

       ç¬¬ä¸€ä¸ªé…ç½®æ˜¯è¿žæŽ¥å·¥åŽ‚,顾名思义,最基本的使用一定是对连接的打开和关闭。我们需要为其配置redis服务器的账户密码,端口号。(这里还可以配置数据库的index,但是我使用时候一直使用redis的默认数据库,也就是第0个)

       æœ€åŽä¸€ä¸ªé…ç½®ç‰¹åˆ«é‡è¦ã€‚这个类似于spring提供的HibernateDaoSupport。

       æŽ¥ä¸‹æ¥ï¼Œå…¨éƒ¨è®²è§£éƒ½å°†å›´ç»•è¿™ä¸ªç±»å±•å¼€ã€‚

       3. RedisTemplate的使用

       è¿™ä¸ªç±»ä½œä¸ºä¸€ä¸ªæ¨¡ç‰ˆç±»ï¼Œæä¾›äº†å¾ˆå¤šå¿«é€Ÿä½¿ç”¨redis的api,而不需要自己来维护连接,事务。

       æœ€åˆçš„时候,我创建的BaseRedisDao是继承自这个类的。继承的好处是我的每个Dao中,都可以自由的控制序列化器,自由的控制自己是否需要事务,这个先不需要了解,跟着我目前的这种配置方法来即可。

       template提供了一系列的operation,比如valueOperation,HashOperation,ListOperation,SetOperation等,用来操作不同数据类型的Redis。

       å¹¶ä¸”,RedisTemplate还提供了对应的*OperationsEditor,用来通过RedisTemplate直接注入对应的Operation。我们暂时不讲这个。

       å¯¹äºŽä¸‹é¢çš„test1方法,我们暂时不用考虑,先了解通过RedisTemplate来使用connection操作Redis。

       Test代码如下:

       package cn.test.spjedis;

       import javax.annotation.Resource;

       import org.junit.Test;

       import org.junit.runner.RunWith;

       import org.springframework.beans.factory.annotation.Autowired;

       import org.springframework.dao.DataAccessException;

       import org.springframework.data.redis.connection.RedisConnection;

       import org.springframework.data.redis.core.RedisCallback;

       import org.springframework.data.redis.core.RedisTemplate;

       import org.springframework.data.redis.core.ValueOperations;

       import org.springframework.test.context.ContextConfiguration;

       import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

       import com.cn.redis2.dao.IncrDao;

       @RunWith(SpringJUnit4ClassRunner.class)

       @ContextConfiguration(locations = "classpath:applicationContext.xml")

       public class TestRedis {

        @Resource(name = "redisTemplate")

        private RedisTemplate<String, String> template; // inject the template as ListOperations

        //至于这个为什么可以注入。需要参考AbstractBeanFactory doGetBean

        //super.setValue(((RedisOperations) value).opsForValue());就这一行代码 依靠一个editor

        @Resource(name = "redisTemplate")

        private ValueOperations<String, Object> vOps;

        public void testSet(){

        template.execute(new RedisCallback<Boolean>() {

        @Override

        public Boolean doInRedis(RedisConnection connection) throws DataAccessException {

        byte [] key = "tempkey".getBytes();

        byte[] value = "tempvalue".getBytes();

        connection.set(key, value);

        return true;

        }

        });

        }

        public void testSet1(){

        vOps.set("tempkey", "tempvalue");

        }

        @Autowired

        private IncrDao incr;

       @Test

        public void addLink() {

        System.out.println(incr.incr());

        System.out.println(incr.get());

        }

       }

       è¿™ä¸ªæ˜¯å¯¹String类型插入的两个测试。test方法中,使用了模版类提交回调(RedisCallBack)的方法来使用jedis connection操作数据。这一部分,有没有似曾相识呢?

       HibernateTemplate的HibernateCallback,以及Hibernate Session类中的doWork以及doReturningWork方法,都是使用了这样的机制,方便对于连接或者session的统一管理。

       public int excuteHqlUpdate(final String hql,final Object ...params){

        return getHibernateTemplate().executeWithNativeSession(new HibernateCallback<Integer>() {

        @Override

        @SuppressWarnings("unchecked")

        public Integer doInHibernate(Session session) throws HibernateException {

        Query queryObject = session.createQuery(hql);

        if (params != null) {

        for (int i = 0; i < params.length; i++) {

        queryObject.setParameter(i, params[i]);

        }

        }

        return queryObject.executeUpdate();

        }

        });

        }

jedis 和 strpin-data-redis 哪一个好

       ä¹‹å‰ä¸€ç›´æ²¡ä»”细看过ShardedJedis的代码,最近遇到了shard后集群扩容后的数据迁移问题。

       ä»Šå¤©åœ¨çœ‹ShardedJedis源码的时候,发现ShardedJedis并没有使用节点的Ip和port做hash,而是用的instance的顺序或者name,太赞了。

       private void initialize(List<S> shards) {

        nodes = new TreeMap<Long, S>();

       for (int i = 0; i != shards.size(); ++i) {

        final S shardInfo = shards.get(i);

        if (shardInfo.getName() == null)

        for (int n = 0; n < * shardInfo.getWeight(); n++) {

        nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n),

        shardInfo);

        }

        else

        for (int n = 0; n < * shardInfo.getWeight(); n++) {

        nodes.put(

        this.algo.hash(shardInfo.getName() + "*"

        + shardInfo.getWeight() + n), shardInfo);

        }

        resources.put(shardInfo, shardInfo.createResource());

        }

        }

       é…ç½®çš„时候也非常简单:

       <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">

        <property name="maxTotal" value=""/>

        <property name="maxIdle" value=""/>

        <property name="minIdle" value="1"/>

        <property name="maxWaitMillis" value=""/>

        <property name="testOnBorrow" value="true"/>

        <property name="testOnReturn" value="true"/>

        <property name="testWhileIdle" value="true"/>

        </bean>

        <bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool" destroy-method="destroy">

        <constructor-arg ref="jedisPoolConfig"/>

        <constructor-arg>

        <list>

        <bean class="redis.clients.jedis.JedisShardInfo">

        <constructor-arg value=".0.0.1"/>

        <constructor-arg type="int" value=""/>

        <constructor-arg value="instance:"/>

        </bean>

        <bean class="redis.clients.jedis.JedisShardInfo">

        <constructor-arg value=".0.0.1"/>

        <constructor-arg type="int" value=""/>

        <constructor-arg value="instance:"/>

        </bean>

        <bean class="redis.clients.jedis.JedisShardInfo">

        <constructor-arg value=".0.0.1"/>

        <constructor-arg type="int" value=""/>

        <constructor-arg value="instance:"/>

        </bean>

        </list>

        </constructor-arg>

        </bean>

       ä¸€å¼€å§‹ä½ å¯ä»¥è®¾ç½®è¶³å¤Ÿå¤šçš„instance,数据扩容的时候,只需要将几个instance的数据copy到别的机器上。

       ç„¶åŽä¿®æ”¹é…ç½®æ–‡ä»¶çš„ip和端口即可。很方便吧?

       å¦å¤–,Jedis还提供了对jedis sentinel pool的封装,所以发生主从切换的时候,web server都不需要重新配置和deploy。高可用性的极佳体现啊。

       @Autowired private JedisSentinelPool pool;

       public void mymethod() {

        Jedis jedis = null;

        try {

        jedis = pool.getResource();

        jedis.hset(....

        } catch (JedisException je) {

        throw je;

        } finally {

        if (jedis != null) pool.returnResource(jedis);

        }

        }

       spring bean的配置:

       <bean id="redisSentinel" class="redis.clients.jedis.JedisSentinelPool">

        <constructor-arg index="0" value="mymaster" />

        <constructor-arg index="1">

        <set>

        <value>hostofsentinel:</value>

        </set>

        </constructor-arg>

        <constructor-arg index="2" ref="jedisPoolConfig" />

        </bean>