您的位置:首页 > 数据库 > Redis

Redis实现分布式锁

2014-03-10 10:05 204 查看
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.    }

 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: