docker 安装 红锁 实现分布式锁方式
作者:互联网
1 docker pull redis 拉取镜像 redis 2 创建redis 映射配置文件(也就是挂在目录) mkdir -p /mydata/redis/conf 3 下载redis.conf 文件 wget http://download.redis.io/redis-stable/redis.conf 4 修改conf 文件内容 bind 127.0.0.1 # 这行要注释掉,解除本地连接限制 protected-mode no # 默认yes,如果设置为yes,则只允许在本机的回环连接,其他机器无法连接。 daemonize no # 默认no 为不守护进程模式,docker部署不需要改为yes,docker run -d本身就是后台启动,不然会冲突 requirepass 123456 # 设置密码(可以不设置) appendonly yes # 持久化 5 复制conf 文件 重新命名 为redis6380.conf,redis6381.conf,redis6382.conf 除了 port 不同 其他均相同 docker run -p 6380:6380 --name order01 -v /mydata/redis/conf/redis6380.conf:/etc/redis/redis6380.conf -v /mydata/redis/data:/data -d redis redis-server /etc/redis/redis6380.conf --appendonly yes docker run -p 6381:6381 --name order02 -v /mydata/redis/conf/redis6381.conf:/etc/redis/redis6381.conf -v /mydata/redis/data:/data -d redis redis-server /etc/redis/redis6381.conf --appendonly yes docker run -p 6382:6382 --name order03 -v /mydata/redis/conf/redis6382.conf:/etc/redis/redis6382.conf -v /mydata/redis/data:/data -d redis redis-server /etc/redis/redis6382.conf --appendonly yes
我们创建了三个不同的redis 实例
然后我们需要配置红锁 我们需要导入一下两个依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.3.2</version> </dependency>
我们需要实现的功能如下: 多个司机 同时抢一个订单,在多个订单服务中,只有一个司机能抢到, 因此我们需要依赖分布式锁来实现 具体就是redisson的红锁
DROP TABLE IF EXISTS `tbl_order`; CREATE TABLE `tbl_order` ( `order_id` int(8) NOT NULL, `order_status` int(8) DEFAULT NULL, PRIMARY KEY (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of tbl_order -- ---------------------------- INSERT INTO `tbl_order` VALUES ('1', '1');
DROP TABLE IF EXISTS `tbl_order_lock`; CREATE TABLE `tbl_order_lock` ( `order_id` int(8) NOT NULL, `driver_id` int(8) DEFAULT NULL, PRIMARY KEY (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
当多个司机抢一个订单,抢到订单的司机会 将order_status 改为1 并输出抢订单成功 其他没有抢到订单的司机 则输出抢订单失败
@Component public class RedisConfig { /*红锁 */ @Bean(name = "redissonClient01") public RedissonClient redissonClient01(){ Config config = new Config(); config.useSingleServer().setAddress("192.168.0.137:6380").setDatabase(0); RedissonClient redissonClient1 = Redisson.create(config); return redissonClient1; } @Bean(name = "redissonClient02") public RedissonClient redissonClient02(){ Config config = new Config(); config.useSingleServer().setAddress("192.168.0.137:6381").setDatabase(0); RedissonClient redissonClient2 = Redisson.create(config); return redissonClient2; } @Bean(name = "redissonClient03") public RedissonClient redissonClient03(){ Config config = new Config(); config.useSingleServer().setAddress("192.168.0.137:6382").setDatabase(0); RedissonClient redissonClient3 = Redisson.create(config); return redissonClient3; } }
@RestController @RequestMapping("/grab") public class GrabOrderController { @Autowired GrabService grabService; @GetMapping("/do/{orderId}") public String grab(@PathVariable("orderId")int orderId,int driverId){ System.out.println("orderId:"+orderId+",driverId:"+driverId); grabService.grab(orderId,driverId); return ""; } }
@Service public class GrabServiceImpl implements GrabService { @Autowired private RedisConfig redisConfig; @Autowired TblOrderService tblOrderService; /*红锁实现分布式锁*/ @Override public void grab(int orderId, int driverId) { /*生成订单key*/ String RedLockKey = (RedisKeyConstant.GRAB_LOCK_ORDER_KEY_PRE + orderId).intern(); RLock lock01 = redisConfig.redissonClient01().getLock(RedLockKey); RLock lock02 = redisConfig.redissonClient02().getLock(RedLockKey); RLock lock03 = redisConfig.redissonClient03().getLock(RedLockKey); // 同时加锁:lock01 lock02 lock03 RedissonRedLock lock = new RedissonRedLock(lock01, lock02, lock03); // 红锁在大部分节点上加锁成功就算成功。 try { lock.lock(); try { /* TimeUnit.MINUTES.sleep(1);*/ } catch (Exception e) { e.printStackTrace(); } System.out.println("司机:"+driverId+" 执行抢单逻辑"); /*抢到锁的司机 修改订单状态 为1 */ boolean grab = tblOrderService.grab(orderId, driverId); if(grab){ System.out.println("司机:"+driverId+" 抢单成功"); /*就把该司机的driverid 和 订单id 绑定在一起*/ }else { System.out.println("司机:"+driverId+" 抢单失败"); } } finally { lock.unlock(); } } }
@Override public boolean grab(int orderId, int driverId) { TblOrderEntity order = tblOrderDao.selectById(orderId); if(order.getOrderStatus().intValue()==0){ order.setOrderStatus(1); tblOrderDao.updateById(order); return true; }else return false; } }
为了测试 我们启动两个service-order 服务来提供测试
启动一台后 修改端口 再次启动该服务
然后我们需要 一个api 接口服务来调用我们创建好的这两个服务
我们利用openFeign 来远程调用service-order 这两个服务 (loadbalancer) 请求消息会均摊到这两个服务上去
用Jmeter 测试 一次1秒发送10条消息 每条消息的orderId 相同 但是driverId不同(我们引入Jmeter自带的计数器 来实现driverId的自增)来模拟多个司机在同一时间 堆同一订单 进行抢单操作
因为涉及到的是分布式锁 我们使用的redsson 的红锁来实现分布式锁
标签:orderId,红锁,int,driverId,redis,conf,docker,order,分布式 来源: https://www.cnblogs.com/Lcch/p/16614476.html