55use RedisException ;
66use support \Redis as RedisClient ;
77use Workerman \Worker ;
8- use Workerman \Timer ;
98
109class Redis implements DriverInterface
1110{
@@ -16,20 +15,28 @@ class Redis implements DriverInterface
1615 */
1716 public function __construct (?Worker $ worker , protected string $ connection )
1817 {
19- if ($ worker ) {
20- Timer::add (24 * 60 * 60 , function () {
21- $ this ->clearExpire ();
22- });
23- }
24- $ this ->clearExpire ();
18+
2519 }
26-
20+
2721 /**
2822 * @throws RedisException
2923 */
3024 public function increase (string $ key , int $ ttl = 24 * 60 * 60 , $ step = 1 ): int
3125 {
32- return RedisClient::connection ($ this ->connection )->hIncrBy ('rate-limiter- ' . date ('Y-m-d ' ), "$ key- " . $ this ->getExpireTime ($ ttl ) . '- ' . $ ttl , $ step ) ?: 0 ;
26+ static $ lastExpiredHashKey = null ;
27+ $ connection = RedisClient::connection ($ this ->connection );
28+ $ hashKey = 'rate-limiter- ' . date ('Y-m-d ' );
29+ $ field = $ key . '- ' . $ this ->getExpireTime ($ ttl ) . '- ' . $ ttl ;
30+
31+ $ count = $ connection ->hIncrBy ($ hashKey , $ field , $ step ) ?: 0 ;
32+
33+ if ($ lastExpiredHashKey !== $ hashKey ) {
34+ $ expireAt = strtotime (date ('Y-m-d ' ) . ' 23:59:59 ' ) + 300 ;
35+ $ connection ->expireAt ($ hashKey , $ expireAt );
36+ $ lastExpiredHashKey = $ hashKey ;
37+ }
38+
39+ return $ count ;
3340 }
3441
3542 /**
@@ -40,19 +47,4 @@ protected function getExpireTime($ttl): int
4047 {
4148 return ceil (time () / $ ttl ) * $ ttl ;
4249 }
43-
44- /**
45- * @return void
46- * @throws RedisException
47- */
48- protected function clearExpire (): void
49- {
50- $ keys = RedisClient::connection ($ this ->connection )->keys ('rate-limiter-* ' );
51- foreach ($ keys as $ key ) {
52- if (!str_contains ($ key , 'rate-limiter- ' . date ('Y-m-d ' ))) {
53- $ key = str_replace (config ('redis. ' . $ this ->connection . '.prefix ' , '' ), '' , $ key );
54- RedisClient::connection ($ this ->connection )->del ($ key );
55- }
56- }
57- }
58- }
50+ }
0 commit comments