Skip to content

Commit 61802ed

Browse files
committed
[redis] Implement redis support
1 parent 3206dbb commit 61802ed

File tree

1 file changed

+209
-1
lines changed

1 file changed

+209
-1
lines changed

cache.php

Lines changed: 209 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,21 @@
88
define('ENABLE_OPCACHE', extension_loaded('Zend OPcache'));
99
define('ENABLE_REALPATH', function_exists('realpath_cache_size'));
1010
define('ENABLE_MEMCACHE', extension_loaded('memcache') || extension_loaded('memcached'));
11+
define('ENABLE_REDIS', extension_loaded('redis'));
1112

1213
// Memcache configuration
1314
define('MEMCACHE_HOST', getenv('MEMCACHE_HOST') ?: '127.0.0.1');
1415
define('MEMCACHE_PORT', getenv('MEMCACHE_PORT') ?: 11211);
1516
define('MEMCACHE_USER', getenv('MEMCACHE_USER') ?: null);
1617
define('MEMCACHE_PASSWORD', getenv('MEMCACHE_PASSWORD') ?: null);
1718

19+
// Redis configuration
20+
define('REDIS_HOST', getenv('REDIS_HOST') ?: '127.0.0.1');
21+
define('REDIS_PORT', getenv('REDIS_PORT') ?: 6379);
22+
define('REDIS_PASSWORD', getenv('REDIS_PASSWORD') ?: null);
23+
define('REDIS_DATABASE', getenv('REDIS_DATABASE') ?: null);
24+
define('REDIS_SIZE', getenv('REDIS_SIZE') ?: null);
25+
1826
if (ENABLE_APC) {
1927
if (!extension_loaded('apcu')) {
2028
function apcu_cache_info($limited = false) { return apc_cache_info('user', $limited); }
@@ -88,6 +96,40 @@ function __construct($search = null) { parent::__construct('user', $search); }
8896
}
8997
}
9098

99+
if (ENABLE_REDIS) {
100+
$redis = new Redis();
101+
$redis->connect(REDIS_HOST, REDIS_PORT);
102+
103+
if (!empty(REDIS_PASSWORD))
104+
$redis->auth(REDIS_PASSWORD);
105+
106+
$redis_db = 0;
107+
$redis_dbs = $redis->config('GET', 'databases');
108+
$redis_db_select = !is_numeric(REDIS_DATABASE) && !empty($redis_dbs);
109+
$redis_memory = $redis->info('memory');
110+
111+
if (!$redis_db_select)
112+
$redis_db = REDIS_DATABASE;
113+
else if (!empty($_COOKIE['redis_db']))
114+
$redis_db = (int)$_COOKIE['redis_db'];
115+
116+
$redis->select($redis_db);
117+
118+
if( is_action('redis_clear') ) {
119+
$redis->flushDb();
120+
redirect('?');
121+
}
122+
123+
if( is_action('redis_delete') ) {
124+
$list = redis_keys(get_selector());
125+
126+
foreach ($list as $key => $item)
127+
$redis->del($key);
128+
129+
redirect( '?action=redis_select&selector=' . $_GET['selector'] );
130+
}
131+
}
132+
91133
function val_to_str($value) {
92134
return htmlentities(var_export($value, true));
93135
}
@@ -223,6 +265,104 @@ function memcache_ref() {
223265
return $keys;
224266
}
225267

268+
function redis_mem( $key ) {
269+
global $redis_memory;
270+
271+
if( $key == 'free' )
272+
return max(redis_mem('total') - redis_mem('used'), 0);
273+
274+
if( $key == 'total' && !empty($redis_memory['maxmemory']) )
275+
return $redis_memory['maxmemory'];
276+
277+
if( $key == 'total' && !empty($redis_memory['total_system_memory']) )
278+
return $redis_memory['total_system_memory'];
279+
280+
if( $key == 'total' && !empty(REDIS_SIZE))
281+
return (int)REDIS_SIZE;
282+
283+
if( $key == 'total')
284+
return redis_mem('used');
285+
286+
if ($key == 'used')
287+
return $redis_memory['used_memory'];
288+
289+
if ($key == 'overhead' && !empty($redis_memory['used_memory_overhead']))
290+
return $redis_memory['used_memory_overhead'];
291+
292+
return 0;
293+
}
294+
295+
function redis_get_key($key, &$found = false) {
296+
global $redis;
297+
298+
$type = $redis->type($key);
299+
$found = $redis->exists($key);
300+
$value = null;
301+
302+
if ($type == Redis::REDIS_STRING || $type == Redis::REDIS_NOT_FOUND)
303+
$value = $redis->get($key);
304+
else if ($type == Redis::REDIS_HASH)
305+
$value == $redis->hgetall($key);
306+
else if ($type == Redis::REDIS_LIST)
307+
$value = $redis->lrange(0, -1);
308+
else if ($type == Redis::REDIS_SET || $type == Redis::REDIS_ZSET) {
309+
$it = null;
310+
$value = array();
311+
312+
do {
313+
$res = $redis->sscan($key, $it);
314+
315+
if (!is_array($res))
316+
continue;
317+
318+
$value = array_merge($value, $res);
319+
} while ($it > 0);
320+
}
321+
else if ($type == Redis::REDIS_ZSET) {
322+
$len = $redis->zcard($key);
323+
$start = 0;
324+
$value = array();
325+
326+
while($start < $len) {
327+
$stop = $start + 99;
328+
329+
$res = $redis->zrange($key, $start, $stop, true);
330+
331+
$start += 100;
332+
}
333+
}
334+
335+
return $value;
336+
}
337+
338+
function redis_keys($selector) {
339+
global $redis;
340+
$keys = array();
341+
342+
$it = null;
343+
do {
344+
$res = $redis->scan($it);
345+
346+
if (!is_array($res))
347+
continue;
348+
349+
foreach ($res as $key) {
350+
if (!preg_match($selector, $key))
351+
continue;
352+
353+
$keys[$key] = array(
354+
'key' => $key,
355+
'ttl' => $redis->ttl($key),
356+
'type' => $redis->type($key),
357+
'size' => $redis->rawCommand('memory', 'usage', $key)
358+
);
359+
}
360+
361+
} while($it > 0);
362+
363+
return $keys;
364+
}
365+
226366
function human_size( $s ) {
227367
$size = 'B';
228368
$sizes = array( 'KB', 'MB', 'GB' );
@@ -285,7 +425,7 @@ function sort_url($on) {
285425
return '?' . $query;
286426
}
287427

288-
function sort_list(&$list) {
428+
function sort_list($list) {
289429
if( !isset( $_GET['sort'] ) )
290430
return $list;
291431

@@ -676,6 +816,74 @@ function sort_list(&$list) {
676816
<?php endif; ?>
677817
</div>
678818
<?php endif; ?>
819+
820+
<?php if(ENABLE_REDIS): ?>
821+
<h2 id="redis">Redis</h2>
822+
<div>
823+
<h3>Memory <?=human_size(redis_mem('used') + redis_mem('hash'))?> of <?=human_size(redis_mem('total'))?></h3>
824+
<div class="full bar green">
825+
<div class="orange" style="width: <?=percentage(redis_mem('used'), redis_mem('total'))?>%"></div>
826+
<div class="red" style="width: <?=percentage(redis_mem('overhead'), redis_mem('total'))?>%"></div>
827+
</div>
828+
<div>
829+
<h3>Actions</h3>
830+
<form action="?" method="GET">
831+
<label>Cache:
832+
<button name="action" value="redis_clear">Restart</button>
833+
</label>
834+
</form>
835+
<form action="?" method="GET">
836+
<label>Key(s):
837+
<input name="selector" type="text" value="" placeholder=".*" />
838+
</label>
839+
<button type="submit" name="action" value="redis_select">Select</button>
840+
<button type="submit" name="action" value="redis_delete">Delete</button>
841+
</form>
842+
</div>
843+
844+
<?php if( is_action('redis_view') ): ?>
845+
<?php $value = redis_get_key(urldecode($_GET['selector']), $found); ?>
846+
<div>
847+
<h3>Value for <?=htmlentities('"'.urldecode($_GET['selector']).'"')?></h3>
848+
<?php if ($found): ?>
849+
<pre><?=val_to_str($value); ?></pre>
850+
<?php else: ?>
851+
<p>Key not found</p>
852+
<?php endif ?>
853+
</div>
854+
<?php endif ?>
855+
856+
<?php if( is_action('redis_select') ): ?>
857+
<div>
858+
<table>
859+
<thead>
860+
<tr>
861+
<th><a href="<?=sort_url('key')?>">Key</a></th>
862+
<th><a href="<?=sort_url('size')?>">Size</a></th>
863+
<th><a href="<?=sort_url('ttl')?>">TTL</a></th>
864+
<th>Expires</th>
865+
<th>Action</th>
866+
</tr>
867+
</thead>
868+
<tbody>
869+
<?php foreach( sort_list(redis_keys(get_selector())) as $key => $item ):?>
870+
<tr>
871+
<td><?=$item['key']?></td>
872+
<td><?=$item['size']?></td>
873+
<td><?=$item['ttl']?></td>
874+
<td><?=($item['ttl'] < 0 ? 'indefinite' : date('Y-m-d H:i', time() + $item['ttl'] ))?></td>
875+
<td>
876+
<a href="?action=redis_delete&selector=<?=urlencode('^'.$key.'$')?>">Delete</a>
877+
<a href="?action=redis_view&selector=<?=urlencode($key)?>">View</a>
878+
</td>
879+
</tr>
880+
<?php endforeach; ?>
881+
</tbody>
882+
</table>
883+
</div>
884+
<?php endif; ?>
885+
</div>
886+
<?php endif; ?>
679887
</div>
680888
</body>
681889
</html>

0 commit comments

Comments
 (0)