利用sql實現(xiàn)簡單的分布式鎖
分布式鎖和普通鎖的主要區(qū)別在于參與主體跨不同節(jié)點,因此需要考慮到節(jié)點失效和網(wǎng)絡(luò)故障的問題。搞清楚問題要點,可以用各種不同的東西去實現(xiàn),比如redis,zookeeper等。但是其實用sql實現(xiàn)也是非常容易的,下面以postgresql為例進行說明。
1. 方法1:會話鎖
利用postgresql中特有的排他會話級別咨詢鎖。
pg_advisory_lock(key bigint)
pg_advisory_unlock(key bigint)
pg_try_advisory_lock(key bigint)
詳細參考: http://www.postgres.cn/docs/9.4/functions-admin.html#functions-advisory-locks-table
這種鎖是會話級的,在釋放鎖之前,鎖的獲得得者必須一直持有這個會話,也就是連接,否則鎖就會被釋放。
這個特性自然而然地解決了鎖的獲得者發(fā)生故障時鎖的釋放問題。
但是,對于需要長時間持有的鎖,它會產(chǎn)生長連接,而數(shù)據(jù)庫的連接是比較耗資源的,往大了配一般也就幾千個,這是需要注意的地方。
另外一個需要考慮的問題是,當(dāng)網(wǎng)絡(luò)或節(jié)點發(fā)生故障時連接的兩端未必能立刻感知到,因此tcp的keepalive是必須的,幸好postgresql的客戶端和服務(wù)端都支持這個設(shè)置。
下面是服務(wù)端的參數(shù):
tcp_keepalives_idle
tcp_keepalives_interval
tcp_keepalives_count
2. 方法2:期限鎖
鎖對象是持久的,為防止拿到鎖的客戶端奔潰導(dǎo)致鎖無法釋放,每個鎖都有一個過期期限。
在postgresql中可以按下面的方式實現(xiàn)
建表
- postgres=# create table distlock(id int primary key,expired_time interval,owner text,ts timestamptz);
- create table
- postgres=# insert into distlock(id) values(1);
- insert 0 1
加鎖和續(xù)期
- postgres=# update distlock set owner='node1',ts=now(),expired_time=interval '20 second' where id=1 and (owner='node1' or owner is null or now() > ts + expired_time);
- update 1
獲得鎖的客戶端如果要長時間持有鎖必須定期執(zhí)行相同的方法對鎖進行續(xù)租,否則會丟鎖。
此時,其它客戶端取鎖會失敗
- postgres=# update distlock set owner='node2',ts=now(),expired_time=interval '20 second' where id=1 and (owner='node2' or owner is null or now() > ts + expired_time);
- update 0
等鎖過期后取鎖成功
- postgres=# update distlock set owner='node2',ts=now(),expired_time=interval '20 second' where id=1 and (owner='node2' or owner is null or now() > ts + expired_time);
- update 1
釋放鎖
- postgres=# update distlock set owner=null,ts=now() where id=1 and owner='node2';
- update 1
3. 總結(jié)
可以看到用關(guān)系數(shù)據(jù)庫實現(xiàn)分布式鎖并不復(fù)雜。尤其上面基于表實現(xiàn)的鎖輔以靠譜的ha部署可以保障鎖信息的持久性和不丟失,但用表更新實現(xiàn)鎖畢竟比較重,不適合對鎖的性能要求非常高的場景。
http://www.bkjia.com/PHPjc/1117252.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/1117252.htmlTechArticle利用SQL實現(xiàn)簡單的分布式鎖 分布式鎖和普通鎖的主要區(qū)別在于參與主體跨不同節(jié)點,因此需要考慮到節(jié)點失效和網(wǎng)絡(luò)故障的問題。搞清楚問...