使用Redisson模拟Redis单实例下的分布式锁处理业务数据
文字图片描述
模拟描述
多个进程同时处理业务数据,每处理一条业务数据,把业务数据中被处理的次数累加1,初始处理次数为0,SQL为update loan set deal_instance = #{deal_instance}, deal_count = deal_count + 1 where id = #{id}。处理结束后,看是否存在被处理次数大于1的情况发生,若存在则表明业务数据被重复处理了,分布式锁不起作用。
模拟情况说明
- MySQL数据库中有50000条业务数据需要处理
- 部署了4个进程(模拟生产上的4个集群实例)
预期结果
- 业务数据无重复处理的情况发生
结果说明
开始时间:01:50:17.400

结束时间:02:03:13.601
TPS:50000/(02:03:13-01:50:17之间的秒数)=64
无重复处理情况发生

代码
MainClass
package com.creasy.redis; import com.creasy.dao.ILoanDao; import com.creasy.pojo.Loan; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.redisson.Redisson; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.lang.management.ManagementFactory; import java.util.Random; import java.util.concurrent.TimeUnit; / * @author laicreasy */ public class MainLockTest {
private static final Logger log = LoggerFactory.getLogger(MainLockTest.class); private static final long LEASE_TIME = 10; public static void main(String[] args) throws InterruptedException, IOException {
String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //Redis配置 Config config = new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redisson = Redisson.create(config); RLock lock = redisson.getLock("myLock"); while (true){
//获取锁 boolean res = lock.tryLock(new Random().nextInt(10), LEASE_TIME, TimeUnit.SECONDS); if (res) {
//模拟获得锁之后处理业务数据 try {
log.info("Get lock"); SqlSession session = sqlSessionFactory.openSession(); ILoanDao mapper = session.getMapper(ILoanDao.class); Loan loan = mapper.queryLoanWithoutDeal(); if( loan == null ) {
break; } loan.setDeal_instance("PID:" + ManagementFactory.getRuntimeMXBean().getPid()); mapper.updateLoan(loan); session.commit(); session.close(); } finally {
log.info("Release lock"); try{
//释放锁 lock.unlock(); } catch (Exception e){
log.error(e.getMessage(), e); } } } // TimeUnit.MILLISECONDS.sleep(new Random().nextInt(10)); } redisson.shutdown(); } }
讯享网
SQL
讯享网-- 建表语句 DROP TABLE IF EXISTS `loan`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `loan` ( `id` int(11) NOT NULL AUTO_INCREMENT, `deal_instance` varchar(40) DEFAULT NULL, `deal_count` int(10) DEFAULT '0', `loan_amount` int(10) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=50003 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping routines for database 'usersys' -- /*!50003 DROP PROCEDURE IF EXISTS `insert_loan_loop` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; /*!50003 SET @saved_col_connection = @@collation_connection */ ; /*!50003 SET character_set_client = utf8mb4 */ ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_0900_ai_ci */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' */ ; -- 插入50000条数据 DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `insert_loan_loop`() BEGIN DECLARE x INT; SET x = 1; WHILE x <= 50000 DO insert into loan(loan_amount) values (x); SET x = x + 1; END WHILE; END ;; DELIMITER ;
具体代码可看:github

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/33718.html