基于Redis的分布式锁两种实现方式
最近有一个竞拍的项目会用到分布式锁,网上查到的结果是有三种途径可以实现。1.数据库锁机制,2.redis的锁,3.zookeeper。考虑到使用mysql实现会在性能这一块会受影响,zookeeper又是不怎么会。所以使用redis来实现了。
第一种:使用redis的watch命令进行实现
如上图所示:session1在执行修改之前使用watch命令监视了age,然后又在session2更新了age之后,session1在执行exec,在该命令执行的时候应该会检查age值是否更改,现在是已经发生了改变,所以返回执行失败。
基于上述图示写了一段java代码
import redis.clients.jedis.Jedis; import redis.clients.jedis.Transaction; import java.util.List; public class RedisWatchTest extends Thread { private String auctionCode; public RedisWatchTest (String auctionCode) { super(auctionCode); this.auctionCode = auctionCode; } private static int bidPrice = 100; public static void main(String[] args) { System.out.println(Thread.currentThread().getName() + "主线程运行开始!"); //更改key为a的值 Jedis jedis=new Jedis("127.0.0.1",6379); jedis.set("goodsprice","0"); System.out.println("输出初始化值:"+jedis.get("goodsprice")); jedis.close(); RedisWatchTest thread1 = new RedisWatchTest("A001"); RedisWatchTest thread2 = new RedisWatchTest("B001"); thread1.start(); thread2.start(); try{ thread1.join(); thread2.join(); }catch(InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "主线程运行结束!"); } @Override public void run() { System.out.println(Thread.currentThread().getName() + "线程运行开始 "); Jedis jedis=new Jedis("127.0.0.1",6379); try { if(Thread.currentThread().getName()=="B001"){ sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } //监视KEY jedis.watch("goodsprice"); //A先进 String v = jedis.get("goodsprice"); Integer iv = Integer.valueOf(v); //条件都给过 if(bidPrice > iv){ Transaction tx = jedis.multi();// 开启事务 Integer bp = iv + 100; //出价成功,事务未提交 tx.set("goodsprice",String.valueOf(bp)); System.out.println("子线程" + auctionCode + "set成功"); try { if(Thread.currentThread().getName()=="A001"){ sleep(2000); } } catch (InterruptedException e) { e.printStackTrace(); } List<Object> list = tx.exec(); if (list == null ||list.size()==0) { System.out.println("子线程" + auctionCode + ",出价失败"); }else{ System.out.println("子线程"+this.auctionCode +", 出价:"+ jedis.get("goodsprice") +",出价时间:"
+ System.nanoTime()); } }else{ System.out.println("出价低于现有价格!"); } jedis.close(); System.out.println(Thread.currentThread().getName() + "线程运行结束"); } }
执行结果:
main主线程运行开始!
输出初始化值:0
B001线程运行开始
A001线程运行开始