1717 */
1818class AtomicUtil
1919{
20+ private static function autoCleanDB ()
21+ {
22+ if (RandomUtil::percent (20 )) {
23+ ModelUtil::model ('atomic ' )->where ('expire ' , '< ' , time ())->delete ();
24+ }
25+ }
26+
27+
28+ /**
29+ * 生产一个原子值,生产后可以使用 consume 消费
30+ * @param $name string
31+ * @param $value int
32+ * @param $expire int
33+ */
2034 public static function produce ($ name , $ value , $ expire = 3600 )
2135 {
2236 if (RedisUtil::isEnable ()) {
@@ -29,12 +43,15 @@ public static function produce($name, $value, $expire = 3600)
2943 } else {
3044 ModelUtil::insert ('atomic ' , ['name ' => $ name , 'value ' => $ value , 'expire ' => time () + $ expire ]);
3145 }
32- if (RandomUtil::percent (20 )) {
33- ModelUtil::model ('atomic ' )->where ('expire ' , '< ' , time ())->delete ();
34- }
46+ self ::autoCleanDB ();
3547 }
3648 }
3749
50+ /**
51+ * 消费一个原子值
52+ * @param $name string
53+ * @return bool 是否成功
54+ */
3855 public static function consume ($ name )
3956 {
4057 if (RedisUtil::isEnable ()) {
@@ -44,9 +61,7 @@ public static function consume($name)
4461 }
4562 return false ;
4663 } else {
47- if (RandomUtil::percent (20 )) {
48- ModelUtil::model ('atomic ' )->where ('expire ' , '< ' , time ())->delete ();
49- }
64+ self ::autoCleanDB ();
5065 ModelUtil::transactionBegin ();
5166 $ atomic = ModelUtil::getWithLock ('atomic ' , ['name ' => $ name ]);
5267 if (empty ($ atomic )) {
@@ -64,6 +79,10 @@ public static function consume($name)
6479 }
6580 }
6681
82+ /**
83+ * 移除一个原子值
84+ * @param $name
85+ */
6786 public static function remove ($ name )
6887 {
6988 if (RedisUtil::isEnable ()) {
@@ -73,4 +92,66 @@ public static function remove($name)
7392 ModelUtil::delete ('atomic ' , ['name ' => $ name ]);
7493 }
7594 }
95+
96+ /**
97+ * 请求一个互斥锁
98+ * acquire 后必须 release
99+ * @param $name string
100+ * @param $expire int
101+ * @return bool 是否成功
102+ */
103+ public static function acquire ($ name , $ expire = 30 )
104+ {
105+ if (RedisUtil::isEnable ()) {
106+ $ key = "Atomic: $ name " ;
107+ if (RedisUtil::setnx ($ key , time () + $ expire )) {
108+ RedisUtil::expire ($ key , $ expire );
109+ return true ;
110+ }
111+ $ ts = RedisUtil::get ($ key );
112+ if ($ ts < time ()) {
113+ RedisUtil::delete ($ key );
114+ return self ::acquire ($ name , $ expire );
115+ }
116+ return false ;
117+ } else {
118+ self ::autoCleanDB ();
119+ ModelUtil::transactionBegin ();
120+ $ atomic = ModelUtil::getWithLock ('atomic ' , ['name ' => $ name ]);
121+ $ ts = time () + $ expire ;
122+ if (empty ($ atomic )) {
123+ ModelUtil::insert ('atomic ' , [
124+ 'name ' => $ name ,
125+ 'value ' => 1 ,
126+ 'expire ' => $ ts
127+ ]);
128+ ModelUtil::transactionCommit ();
129+ return true ;
130+ }
131+ if ($ atomic ['expire ' ] < time ()) {
132+ ModelUtil::update ('atomic ' , ['name ' => $ name ], [
133+ 'value ' => 1 ,
134+ 'expire ' => $ ts
135+ ]);
136+ ModelUtil::transactionCommit ();
137+ return true ;
138+ }
139+ ModelUtil::transactionCommit ();
140+ return false ;
141+ }
142+ }
143+
144+ /**
145+ * 释放一个互斥锁
146+ * @param $name string
147+ */
148+ public static function release ($ name )
149+ {
150+ if (RedisUtil::isEnable ()) {
151+ $ key = "Atomic: $ name " ;
152+ RedisUtil::delete ($ key );
153+ } else {
154+ ModelUtil::delete ('atomic ' , ['name ' => $ name ]);
155+ }
156+ }
76157}
0 commit comments