redis分布式事务锁案例教学

什么是分布式事务?

分布式事务,说的就是JTA(XA)的事务,只要你能回答出来两段式提交,基本就算你过了,在J2EE企业开发场景比较常用,跨数据库跨应用,准备阶段,提交阶段,这些,做互联网开发的用的比较少,不过因为JTA是事务标准,spring的事务也要基于这个标准来实现,所以了解一些对于开发是有好处的,所以才会问。

什么是分布式锁?

第二个好一些,分布式锁应用场景很多,比如并发场景下对于数据库的更改,或者分布式运行的JOB之类的,都需要一个分布式的锁来让多机对于竞争资源实现序列化的访问,然后实现的话现在通过zookeeper实现的比较多见(但是性能不是很好),也可以通过公用的缓存或者数据库自己来实现。

为了解决并发的问题,需要用到redis分布式事务锁。(会用才是王道!!!)

redis分布式事务锁案例配置:
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-4.1.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
                        http://www.springframework.org/schema/aop
                        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:component-scan base-package="XX.XX.*" />
    <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

    <bean id="disconfMgrBean" class="com.baidu.disconf.client.DisconfMgrBean"
        destroy-method="destroy">
        <property name="scanPackage" value="com.niwodai.tc"></property>
    </bean>
    <bean id="disconfMgrBean2" class="com.baidu.disconf.client.DisconfMgrBeanSecond"
        init-method="init" destroy-method="destroy" />

    <!-- 使用托管方式的disconf配置(无代码侵入, 配置更改会自动reload) -->
    <bean id="configproperties_disconf"
        class="com.baidu.disconf.client.addons.properties.ReloadablePropertiesFactoryBean">
        <property name="locations">
            <list>
                <value>classpath*:job.properties</value>
                <value>classpath*:redis.properties</value>
                <value>classpath*:dubbo-pvd.properties</value>
                <value>classpath*:dubbo-consumer.properties</value>
                <value>classpath*:active-MQ.properties</value>
            </list>
        </property>
    </bean>

    <!-- 配置线程池 -->
    <!-- <bean id="startTransferThreadPool"
        class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        线程池维护线程的最少数量
        <property name="corePoolSize" value="${corePoolSize}" />
        线程池维护线程所允许的空闲时间
        <property name="keepAliveSeconds" value="${keepAliveSeconds}" />
        线程池维护线程的最大数量
        <property name="maxPoolSize" value="${maxPoolSize}" />
        线程池所使用的缓冲队列
        <property name="queueCapacity" value="${queueCapacity}" />
    </bean> -->

        <bean id="propertyConfigurerForProject1"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="ignoreResourceNotFound" value="true" />
        <property name="ignoreUnresolvablePlaceholders" value="true" />
        <property name="propertiesArray">
            <list>
                <ref bean="configproperties_disconf" />
            </list>
        </property>
    </bean>
    

    <!-- 引入系统中当前环境下所有的properties文件 -->
     <bean id="propertyPlaceholderConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="ignoreUnresolvablePlaceholders" value="true" />
        <property name="locations">
            <list>
                <value>classpath*:properties/*.properties</value>
            </list>
        </property>
    </bean>

    <import resource="classpath*:spring/dataSource.xml" />

    <import resource="classpath*:spring/mybatis.xml" />

    <!-- <import resource="classpath*:spring/mybatis-config.xml" /> -->

    <import resource="classpath*:spring/service.xml" />

    <import resource="classpath*:spring/facade.xml" />

    <import resource="classpath*:spring/dubbo-common.xml" />

    <import resource="classpath*:spring/dubbo-consumer.xml" />

    <import resource="classpath*:spring/dubbo-product-consumer.xml" />

    <import resource="classpath*:spring/dubbo-member-consumer.xml" />

    <import resource="classpath*:spring/dubbo-msg-consumer.xml" />

    <import resource="classpath*:spring/repay-redis.xml" />

    <import resource="classpath*:spring/spring-activeMQ.xml" />

    <import resource="classpath*:spring/dubbo-cpn-consumer.xml" />
    
    <import resource="classpath*:disconf/spring/notify/notification-client-jms.xml" />
    
    <import resource="classpath*:disconf/spring/notify/notification-client-mail-jms.xml" />
    
    <import resource="classpath*:spring/job/job-*.xml" />
    
    <import resource="classpath*:spring/applicationContext-account-postmq.xml" />
    
</beans>

repay-redis.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/cache
           http://www.springframework.org/schema/cache/spring-cache.xsd">
           
              <!-- redis配置    -->
    <bean id="stringJedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy"
          p:host-name="${repay.string.redis.host}" p:port="${repay.string.redis.port}" p:timeout="${repay.string.redis.timeout}" p:usePool="${repay.string.redis.usePool}"
           p:password="${repay.string.redis.password}">
        <constructor-arg index="0" ref="stringJedisPoolConfig" />
    </bean>

    

   
    <bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"
          p:connection-factory-ref="stringJedisConnectionFactory" p:enableTransactionSupport="false"/>
          
    <bean id="stringJedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="${repay.string.redis.maxTotal}" />
        <property name="maxIdle" value="${repay.string.redis.maxIdle}" />
        <property name="minIdle" value="${repay.string.redis.minIdle}" />
        <property name="maxWaitMillis" value="${repay.string.redis.maxWaitMillis}" />
        <property name="testOnBorrow" value="${repay.string.redis.testOnBorrow}" />
        <property name="softMinEvictableIdleTimeMillis" value="500" />
           <property name="timeBetweenEvictionRunsMillis" value="1000" />
    </bean>
 
</beans>

参数配置:
repay.string.redis.host=192.168.0.172
repay.string.redis.port=6379
repay.string.redis.timeout=15000
repay.string.redis.usePool=TRUE
repay.string.redis.password=123
#repay.string.redis.database=2
repay.string.redis.maxTotal=100
repay.string.redis.maxIdle=50
repay.string.redis.minIdle=20
repay.string.redis.maxWaitMillis=10000
repay.string.redis.testOnBorrow=TRUE

java代码:
@Resource(name = "stringRedisTemplate")
private StringRedisTemplate stringRedisTemplate;

String key = "A_" + realPayer.getLid();//程序唯一key

            // REDIS锁住在线还款,避免并发问题()
            if (stringRedisTemplate.opsForValue().setIfAbsent(key, realPayer.getLid().toString())) {
                stringRedisTemplate.expire(key, 5, TimeUnit.MINUTES);
            } else {
                throw new BusinessException("");
            }

                  try {
                        //逻辑处理
            } catch (Exception e) {
            } finally {
                stringRedisTemplate.delete(key);
            }
谨记 不管处理如何都要有 finally {
                stringRedisTemplate.delete(key);
            }

maven 包:
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.6.0.RELEASE</version>
</dependency>

猜你喜欢

转载自blog.csdn.net/damoneric_guo/article/details/69384968