Redis分布式
Redis分布式
一、 Redis分布式概述
1. 什么是Redis分布式
Redis分布式是指将Redis数据分布到多个Redis节点上,通过集群方式提供更高性能、更大容量和更好可用性的解决方案。
1.2 为什么需要Redis分布式
数据量增长:单机内存容量有限
高并发需求:单机性能瓶颈
高可用性:避免单点故障
可扩展性:支持业务动态扩容
1.3 Redis分布式方案对比
| 方案 | 优点 | 缺点 | 使用场景 |
|---|---|---|---|
| 主从复制 | 部署简单,读写分离 | 写操作单点,故障需手动切换 | 读多写少,数据备份 |
| Redis Sentinel | 自动故障转移,高可用 | 配置复杂,扩容不便 | 生产环境高可用 |
| Redis Cluster | 数据分片,自动故障转移 | 客户端兼容性要求,迁移复杂 | 大数据量,高并发 |
二、 Redis分布式方案搭建
2.1 主从复制搭建
配置文件示例
主节点 (master.conf):
1port 6379
2daemonize yes
3pidfile /var/run/redis_6379.pid
4logfile "/var/log/redis_6379.log"
从节点 (slave.conf):
port 6380
daemonize yes
pidfile /var/run/redis_6380.pid
logfile "/var/log/redis_6380.log"
slaveof 127.0.0.1 6379
启动命令
1# 启动主节点
2redis-server master.conf
3
4# 启动从节点
5redis-server slave.conf
2.2 Redis Sentinel搭建
Sentinel配置文件
sentinel.conf:
1port 26379
2daemonize yes
3sentinel monitor mymaster 127.0.0.1 6379 2
4sentinel down-after-milliseconds mymaster 5000
5sentinel failover-timeout mymaster 15000
启动Sentinel
1redis-sentinel sentinel.conf
2.3 Redis Cluster搭建 ( 企业级推荐方案首选)
集群节点配置
创建6个节点配置文件(3主3从),端口7000 7001 7002 7003 7004 7005:
node-7000.conf如:
1port 7000
2cluster-enabled yes
3cluster-config-file nodes-7000.conf
4cluster-node-timeout 5000
5appendonly yes
启动集群节点
1for port in 7000 7001 7002 7003 7004 7005; do
2 redis-server node-${port}.conf &
3done
创建集群
1redis-cli --cluster create \
2127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
3127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
4--cluster-replicas 1
三、 Redis分布式应用场景
3.1 会话存储(Session Storage)
1// 分布式Session存储
2$sessionHandler = new RedisSessionHandler($redisCluster);
3session_set_save_handler($sessionHandler, true);
4session_start();
3.2 缓存集群
热点数据分布式缓存
缓存击穿防护
多级缓存架构
3.3 分布式锁
1class RedisDistributedLock {
2 private $redis;
3
4 public function __construct($redis) {
5 $this->redis = $redis;
6 }
7
8 public function lock($key, $timeout = 10) {
9 $identifier = uniqid();
10 $end = time() + $timeout;
11
12 while (time() < $end) {
13 if ($this->redis->set($key, $identifier, ['NX', 'EX' => $timeout])) {
14 return $identifier;
15 }
16 usleep(100000); // 100ms
17 }
18 return false;
19 }
20
21 public function unlock($key, $identifier) {
22 $script = "
23 if redis.call('get', KEYS[1]) == ARGV[1] then
24 return redis.call('del', KEYS[1])
25 else
26 return 0
27 end
28 ";
29 return $this->redis->eval($script, [$key, $identifier], 1);
30 }
31}
3.4 消息队列
1// 分布式消息队列
2class RedisMessageQueue {
3 private $redis;
4 private $queueName;
5
6 public function __construct($redis, $queueName) {
7 $this->redis = $redis;
8 $this->queueName = $queueName;
9 }
10
11 public function push($message) {
12 return $this->redis->lpush($this->queueName, json_encode($message));
13 }
14
15 public function pop($timeout = 0) {
16 $result = $this->redis->brpop($this->queueName, $timeout);
17 return $result ? json_decode($result[1], true) : null;
18 }
19}
四、PHP中的Redis分布式应用
4.1 安装Redis扩展
1# 安装PHP Redis扩展
2pecl install redis
4.2连接Redis Cluster
1<?php
2class RedisClusterManager {
3 private $cluster;
4
5 public function __construct($nodes) {
6 $this->cluster = new RedisCluster(null, $nodes);
7 }
8
9 public function set($key, $value, $ttl = null) {
10 return $ttl ?
11 $this->cluster->setex($key, $ttl, $value) :
12 $this->cluster->set($key, $value);
13 }
14
15 public function get($key) {
16 return $this->cluster->get($key);
17 }
18
19 public function mget($keys) {
20 return $this->cluster->mget($keys);
21 }
22}
23
24// 使用示例
25$nodes = [
26 '127.0.0.1:7000',
27 '127.0.0.1:7001',
28 '127.0.0.1:7002'
29];
30
31$redisCluster = new RedisClusterManager($nodes);
32$redisCluster->set('user:1001', json_encode(['name' => 'John', 'age' => 25]));
4.3 分布式ID生成器
1class DistributedIdGenerator {
2 private $redis;
3 private $key;
4
5 public function __construct($redis, $key = 'distributed:id') {
6 $this->redis = $redis;
7 $this->key = $key;
8 }
9
10 public function generate($step = 1) {
11 return $this->redis->incrby($this->key, $step);
12 }
13
14 public function generateWithTimestamp($prefix = '') {
15 $timestamp = (int)(microtime(true) * 1000);
16 $sequence = $this->redis->incr($this->key . ':seq');
17 return $prefix . $timestamp . str_pad($sequence % 1000, 3, '0', STR_PAD_LEFT);
18 }
19}
4.4 分布式计数器
1class DistributedCounter {
2 private $redis;
3
4 public function __construct($redis) {
5 $this->redis = $redis;
6 }
7
8 public function increment($key, $value = 1, $ttl = 3600) {
9 $script = "
10 local current = redis.call('incrby', KEYS[1], ARGV[1])
11 if current == tonumber(ARGV[1]) then
12 redis.call('expire', KEYS[1], ARGV[2])
13 end
14 return current
15 ";
16 return $this->redis->eval($script, [$key, $value, $ttl], 1);
17 }
18
19 public function get($key) {
20 return $this->redis->get($key) ?: 0;
21 }
22}
4.5 分布式限流器
1class DistributedRateLimiter {
2 private $redis;
3
4 public function __construct($redis) {
5 $this->redis = $redis;
6 }
7
8 public function isAllowed($key, $limit, $window) {
9 $script = "
10 local key = KEYS[1]
11 local limit = tonumber(ARGV[1])
12 local window = tonumber(ARGV[2])
13 local current = redis.call('GET', key) or 0
14
15 if tonumber(current) >= limit then
16 return 0
17 else
18 redis.call('INCR', key)
19 if tonumber(current) == 0 then
20 redis.call('EXPIRE', key, window)
21 end
22 return 1
23 end
24 ";
25
26 return (bool)$this->redis->eval($script, [$key, $limit, $window], 1);
27 }
28}
发表评论