`

Redis实现分布式锁

阅读更多
01./** 
02. * @author http://blog.csdn.net/java2000_wl 
03. * @version <b>1.0.0</b> 
04. */  
05.public class RedisBillLockHandler implements IBatchBillLockHandler {  
06.  
07.    private static final Logger LOGGER = LoggerFactory.getLogger(RedisBillLockHandler.class);  
08.  
09.    private static final int DEFAULT_SINGLE_EXPIRE_TIME = 3;  
10.      
11.    private static final int DEFAULT_BATCH_EXPIRE_TIME = 6;  
12.  
13.    private final JedisPool jedisPool;  
14.      
15.    /** 
16.     * 构造 
17.     * @author http://blog.csdn.net/java2000_wl 
18.     */  
19.    public RedisBillLockHandler(JedisPool jedisPool) {  
20.        this.jedisPool = jedisPool;  
21.    }  
22.  
23.    /** 
24.     * 获取锁  如果锁可用   立即返回true,  否则返回false 
25.     * @author http://blog.csdn.net/java2000_wl 
26.     * @param billIdentify 
27.     * @return 
28.     */  
29.    public boolean tryLock(IBillIdentify billIdentify) {  
30.        return tryLock(billIdentify, 0L, null);  
31.    }  
32.  
33.    /** 
34.     * 锁在给定的等待时间内空闲,则获取锁成功 返回true, 否则返回false 
35.     * @author http://blog.csdn.net/java2000_wl 
36.     * @param billIdentify 
37.     * @param timeout 
38.     * @param unit 
39.     * @return 
40.     */  
41.    public boolean tryLock(IBillIdentify billIdentify, long timeout, TimeUnit unit) {  
42.        String key = (String) billIdentify.uniqueIdentify();  
43.        Jedis jedis = null;  
44.        try {  
45.            jedis = getResource();  
46.            long nano = System.nanoTime();  
47.            do {  
48.                LOGGER.debug("try lock key: " + key);  
49.                Long i = jedis.setnx(key, key);  
50.                if (i == 1) {   
51.                    jedis.expire(key, DEFAULT_SINGLE_EXPIRE_TIME);  
52.                    LOGGER.debug("get lock, key: " + key + " , expire in " + DEFAULT_SINGLE_EXPIRE_TIME + " seconds.");  
53.                    return Boolean.TRUE;  
54.                } else { // 存在锁  
55.                    if (LOGGER.isDebugEnabled()) {  
56.                        String desc = jedis.get(key);  
57.                        LOGGER.debug("key: " + key + " locked by another business:" + desc);  
58.                    }  
59.                }  
60.                if (timeout == 0) {  
61.                    break;  
62.                }  
63.                Thread.sleep(300);  
64.            } while ((System.nanoTime() - nano) < unit.toNanos(timeout));  
65.            return Boolean.FALSE;  
66.        } catch (JedisConnectionException je) {  
67.            LOGGER.error(je.getMessage(), je);  
68.            returnBrokenResource(jedis);  
69.        } catch (Exception e) {  
70.            LOGGER.error(e.getMessage(), e);  
71.        } finally {  
72.            returnResource(jedis);  
73.        }  
74.        return Boolean.FALSE;  
75.    }  
76.  
77.    /** 
78.     * 如果锁空闲立即返回   获取失败 一直等待 
79.     * @author http://blog.csdn.net/java2000_wl 
80.     * @param billIdentify 
81.     */  
82.    public void lock(IBillIdentify billIdentify) {  
83.        String key = (String) billIdentify.uniqueIdentify();  
84.        Jedis jedis = null;  
85.        try {  
86.            jedis = getResource();  
87.            do {  
88.                LOGGER.debug("lock key: " + key);  
89.                Long i = jedis.setnx(key, key);  
90.                if (i == 1) {   
91.                    jedis.expire(key, DEFAULT_SINGLE_EXPIRE_TIME);  
92.                    LOGGER.debug("get lock, key: " + key + " , expire in " + DEFAULT_SINGLE_EXPIRE_TIME + " seconds.");  
93.                    return;  
94.                } else {  
95.                    if (LOGGER.isDebugEnabled()) {  
96.                        String desc = jedis.get(key);  
97.                        LOGGER.debug("key: " + key + " locked by another business:" + desc);  
98.                    }  
99.                }  
100.                Thread.sleep(300);   
101.            } while (true);  
102.        } catch (JedisConnectionException je) {  
103.            LOGGER.error(je.getMessage(), je);  
104.            returnBrokenResource(jedis);  
105.        } catch (Exception e) {  
106.            LOGGER.error(e.getMessage(), e);  
107.        } finally {  
108.            returnResource(jedis);  
109.        }  
110.    }  
111.  
112.    /** 
113.     * 释放锁 
114.     * @author http://blog.csdn.net/java2000_wl 
115.     * @param billIdentify 
116.     */  
117.    public void unLock(IBillIdentify billIdentify) {  
118.        List<IBillIdentify> list = new ArrayList<IBillIdentify>();  
119.        list.add(billIdentify);  
120.        unLock(list);  
121.    }  
122.  
123.    /** 
124.     * 批量获取锁  如果全部获取   立即返回true, 部分获取失败 返回false 
125.     * @author http://blog.csdn.net/java2000_wl 
126.     * @date 2013-7-22 下午10:27:44 
127.     * @param billIdentifyList 
128.     * @return 
129.     */  
130.    public boolean tryLock(List<IBillIdentify> billIdentifyList) {  
131.        return tryLock(billIdentifyList, 0L, null);  
132.    }  
133.      
134.    /** 
135.     * 锁在给定的等待时间内空闲,则获取锁成功 返回true, 否则返回false 
136.     * @author http://blog.csdn.net/java2000_wl 
137.     * @param billIdentifyList 
138.     * @param timeout 
139.     * @param unit 
140.     * @return 
141.     */  
142.    public boolean tryLock(List<IBillIdentify> billIdentifyList, long timeout, TimeUnit unit) {  
143.        Jedis jedis = null;  
144.        try {  
145.            List<String> needLocking = new CopyOnWriteArrayList<String>();    
146.            List<String> locked = new CopyOnWriteArrayList<String>();     
147.            jedis = getResource();  
148.            long nano = System.nanoTime();  
149.            do {  
150.                // 构建pipeline,批量提交  
151.                Pipeline pipeline = jedis.pipelined();  
152.                for (IBillIdentify identify : billIdentifyList) {  
153.                    String key = (String) identify.uniqueIdentify();  
154.                    needLocking.add(key);  
155.                    pipeline.setnx(key, key);  
156.                }  
157.                LOGGER.debug("try lock keys: " + needLocking);  
158.                // 提交redis执行计数  
159.                List<Object> results = pipeline.syncAndReturnAll();  
160.                for (int i = 0; i < results.size(); ++i) {  
161.                    Long result = (Long) results.get(i);  
162.                    String key = needLocking.get(i);  
163.                    if (result == 1) {  // setnx成功,获得锁  
164.                        jedis.expire(key, DEFAULT_BATCH_EXPIRE_TIME);  
165.                        locked.add(key);  
166.                    }   
167.                }  
168.                needLocking.removeAll(locked);  // 已锁定资源去除  
169.                  
170.                if (CollectionUtils.isEmpty(needLocking)) {  
171.                    return true;  
172.                } else {      
173.                    // 部分资源未能锁住  
174.                    LOGGER.debug("keys: " + needLocking + " locked by another business:");  
175.                }  
176.                  
177.                if (timeout == 0) {   
178.                    break;  
179.                }  
180.                Thread.sleep(500);    
181.            } while ((System.nanoTime() - nano) < unit.toNanos(timeout));  
182.  
183.            // 得不到锁,释放锁定的部分对象,并返回失败  
184.            if (!CollectionUtils.isEmpty(locked)) {  
185.                jedis.del(locked.toArray(new String[0]));  
186.            }  
187.            return false;  
188.        } catch (JedisConnectionException je) {  
189.            LOGGER.error(je.getMessage(), je);  
190.            returnBrokenResource(jedis);  
191.        } catch (Exception e) {  
192.            LOGGER.error(e.getMessage(), e);  
193.        } finally {  
194.            returnResource(jedis);  
195.        }  
196.        return true;  
197.    }  
198.  
199.    /** 
200.     * 批量释放锁 
201.     * @author http://blog.csdn.net/java2000_wl 
202.     * @param billIdentifyList 
203.     */  
204.    public void unLock(List<IBillIdentify> billIdentifyList) {  
205.        List<String> keys = new CopyOnWriteArrayList<String>();  
206.        for (IBillIdentify identify : billIdentifyList) {  
207.            String key = (String) identify.uniqueIdentify();  
208.            keys.add(key);  
209.        }  
210.        Jedis jedis = null;  
211.        try {  
212.            jedis = getResource();  
213.            jedis.del(keys.toArray(new String[0]));  
214.            LOGGER.debug("release lock, keys :" + keys);  
215.        } catch (JedisConnectionException je) {  
216.            LOGGER.error(je.getMessage(), je);  
217.            returnBrokenResource(jedis);  
218.        } catch (Exception e) {  
219.            LOGGER.error(e.getMessage(), e);  
220.        } finally {  
221.            returnResource(jedis);  
222.        }  
223.    }  
224.      
225.    /** 
226.     * @author http://blog.csdn.net/java2000_wl 
227.     * @date 2013-7-22 下午9:33:45 
228.     * @return 
229.     */  
230.    private Jedis getResource() {  
231.        return jedisPool.getResource();  
232.    }  
233.      
234.    /** 
235.     * 销毁连接 
236.     * @author http://blog.csdn.net/java2000_wl 
237.     * @param jedis 
238.     */  
239.    private void returnBrokenResource(Jedis jedis) {  
240.        if (jedis == null) {  
241.            return;  
242.        }  
243.        try {  
244.            //容错  
245.            jedisPool.returnBrokenResource(jedis);  
246.        } catch (Exception e) {  
247.            LOGGER.error(e.getMessage(), e);  
248.        }  
249.    }  
250.      
251.    /** 
252.     * @author http://blog.csdn.net/java2000_wl 
253.     * @param jedis 
254.     */  
255.    private void returnResource(Jedis jedis) {  
256.        if (jedis == null) {  
257.            return;  
258.        }  
259.        try {  
260.            jedisPool.returnResource(jedis);  
261.        } catch (Exception e) {  
262.            LOGGER.error(e.getMessage(), e);  
263.        }  
264.    } 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics