Caching is one of the most powerful techniques for speeding up applications. While Redis is the industry standard for in‑memory caching, sometimes you want to learn by building your own or experiment with lightweight alternatives. In this post, I’ll show you how to create a Redis‑like cache server in PHP that stores data in a JSON file for persistence.
Why Build Your Own Cache?
- Educational value: Understand how Redis works under the hood.
- Lightweight projects: Use a simple cache without external dependencies.
- Custom features: Extend with your own commands or APIs.
Step 1: Core Data Store
We’ll use a JSON file (cache.json) to persist key‑value pairs. On startup, the server loads this file into memory, and every SET/DEL operation writes back to disk.
<?php
$cacheFile = __DIR__ . "/cache.json";
// Load existing cache
if (file_exists($cacheFile)) {
$store = json_decode(file_get_contents($cacheFile), true);
} else {
$store = [];
}
$ttl = []; // track expiration times
Step 2: Cache Functions
Implement basic commands: SET, GET, and DEL.
function saveCache() {
global $store, $cacheFile;
file_put_contents($cacheFile, json_encode($store, JSON_PRETTY_PRINT));
}
function setKey($key, $value, $expire = null) {
global $store, $ttl;
$store[$key] = $value;
if ($expire) {
$ttl[$key] = time() + $expire;
}
saveCache();
}
function getKey($key) {
global $store, $ttl;
if (isset($ttl[$key]) && time() > $ttl[$key]) {
unset($store[$key], $ttl[$key]);
saveCache();
return null;
}
return $store[$key] ?? null;
}
function delKey($key) {
global $store, $ttl;
unset($store[$key], $ttl[$key]);
saveCache();
}
Step 3: TCP Server
Use PHP’s stream_socket_server to listen for client connections on port 6379 (same as Redis).
$server = stream_socket_server("tcp://127.0.0.1:6379", $errno, $errstr);
if (!$server) {
die("Error: $errstr ($errno)\n");
}
echo "PHP JSON Cache Server running on 127.0.0.1:6379...\n";
while ($client = stream_socket_accept($server)) {
$input = trim(fgets($client));
$parts = explode(" ", $input);
$cmd = strtoupper($parts[0]);
switch ($cmd) {
case "SET":
setKey($parts[1], $parts[2], $parts[3] ?? null);
fwrite($client, "+OK\n");
break;
case "GET":
$val = getKey($parts[1]);
fwrite($client, $val ? "$val\n" : "(nil)\n");
break;
case "DEL":
delKey($parts[1]);
fwrite($client, ":1\n");
break;
default:
fwrite($client, "-ERR unknown command\n");
}
fclose($client);
}
Step 4: Testing
Run the server:
php cache_server.php
Connect with telnet:
telnet 127.0.0.1 6379
SET foo bar 10
+OK
GET foo
bar
Check cache.json:
{
"foo": "bar"
}
Step 5: Deployment Example (Ubuntu)
- Install PHP CLI:
sudo apt update
sudo apt install php-cli -y
- Create directory:
mkdir /opt/php-cache && cd /opt/php-cache
-
Add files:
cache_server.phpandcache.json. -
Systemd service (
/etc/systemd/system/php-cache.service):
[Unit]
Description=PHP JSON Cache Server
After=network.target
[Service]
ExecStart=/usr/bin/php /opt/php-cache/cache_server.php
Restart=always
User=www-data
WorkingDirectory=/opt/php-cache
[Install]
WantedBy=multi-user.target
- Enable & start:
sudo systemctl daemon-reload
sudo systemctl enable php-cache
sudo systemctl start php-cache
Enhancements
- Add REST API endpoints for easier integration.
- Implement more commands (
EXISTS,INCR,KEYS). - Add automatic TTL cleanup.
- Dockerize for portable deployment.
Conclusion
You now have a working Redis‑style cache server in PHP with JSON persistence. While it won’t match Redis in performance, it’s a fantastic way to learn about caching, persistence, and server design. From here, you can extend it into a microservice, wrap it with an API, or containerize it for cloud deployment.
Top comments (0)