|
|
|
|
|
# Redis缓存架构设计
|
|
|
|
|
|
|
|
|
|
|
|
## 一、设计概述
|
|
|
|
|
|
|
|
|
|
|
|
本Redis缓存架构用于存储股票分析系统的热点数据,减少对数据源和数据库的访问,提高系统响应速度。设计采用Redis作为缓存层,主要存储以下数据:
|
|
|
|
|
|
|
|
|
|
|
|
- 实时行情数据
|
|
|
|
|
|
- 板块动量数据
|
|
|
|
|
|
- 市场统计数据
|
|
|
|
|
|
- K线历史数据
|
|
|
|
|
|
- 计算结果缓存
|
|
|
|
|
|
|
|
|
|
|
|
## 二、缓存键设计
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 实时行情缓存
|
|
|
|
|
|
|
|
|
|
|
|
| 缓存类型 | 缓存键格式 | 数据结构 | 过期时间 | 描述 |
|
|
|
|
|
|
|---------|-----------|---------|---------|------|
|
|
|
|
|
|
| 单只股票实时行情 | `realtime:stock:{code}` | Hash | 30分钟 | 存储单只股票的实时行情数据 |
|
|
|
|
|
|
| 全市场实时行情 | `realtime:full` | String | 30分钟 | 存储全市场股票的实时行情数据(压缩) |
|
|
|
|
|
|
| ETF实时行情 | `realtime:etf:{code}` | Hash | 30分钟 | 存储ETF的实时行情数据 |
|
|
|
|
|
|
| 实时行情批次 | `realtime:batch` | Set | 1小时 | 记录最近更新的股票代码 |
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 板块数据缓存
|
|
|
|
|
|
|
|
|
|
|
|
| 缓存类型 | 缓存键格式 | 数据结构 | 过期时间 | 描述 |
|
|
|
|
|
|
|---------|-----------|---------|---------|------|
|
|
|
|
|
|
| 板块动量 | `sector:momentum:{period}:{sort}:{order}:{limit}` | Sorted Set | 1小时 | 存储板块动量数据,按动量值排序 |
|
|
|
|
|
|
| 板块成分股 | `sector:stocks:{sector_code}` | List | 24小时 | 存储板块的成分股列表 |
|
|
|
|
|
|
| 板块基本信息 | `sector:info:{sector_code}` | Hash | 24小时 | 存储板块的基本信息 |
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 市场数据缓存
|
|
|
|
|
|
|
|
|
|
|
|
| 缓存类型 | 缓存键格式 | 数据结构 | 过期时间 | 描述 |
|
|
|
|
|
|
|---------|-----------|---------|---------|------|
|
|
|
|
|
|
| 市场统计 | `market:stats` | Hash | 1小时 | 存储市场统计数据 |
|
|
|
|
|
|
| 指数数据 | `market:index:{code}` | Hash | 1小时 | 存储指数的实时数据 |
|
|
|
|
|
|
| 涨跌分布 | `market:distribution` | Hash | 1小时 | 存储市场涨跌分布数据 |
|
|
|
|
|
|
|
|
|
|
|
|
### 4. K线数据缓存
|
|
|
|
|
|
|
|
|
|
|
|
| 缓存类型 | 缓存键格式 | 数据结构 | 过期时间 | 描述 |
|
|
|
|
|
|
|---------|-----------|---------|---------|------|
|
|
|
|
|
|
| K线数据 | `kline:{code}:{period}:{days}` | List | 1天 | 存储股票的K线数据 |
|
|
|
|
|
|
| K线数据(压缩) | `kline:compressed:{code}:{period}:{days}` | String | 1天 | 存储压缩后的K线数据 |
|
|
|
|
|
|
|
|
|
|
|
|
### 5. 计算结果缓存
|
|
|
|
|
|
|
|
|
|
|
|
| 缓存类型 | 缓存键格式 | 数据结构 | 过期时间 | 描述 |
|
|
|
|
|
|
|---------|-----------|---------|---------|------|
|
|
|
|
|
|
| 技术指标 | `indicator:{code}:{indicator}:{params}` | Hash | 1天 | 存储计算好的技术指标 |
|
|
|
|
|
|
| 选股结果 | `stock:selection:{strategy}:{params}` | Set | 1小时 | 存储选股策略的结果 |
|
|
|
|
|
|
| 回测结果 | `backtest:{strategy}:{params}` | Hash | 24小时 | 存储回测结果 |
|
|
|
|
|
|
|
|
|
|
|
|
## 三、数据结构选择
|
|
|
|
|
|
|
|
|
|
|
|
### 1. Hash
|
|
|
|
|
|
- **适用场景**:存储结构化数据,如实时行情、板块信息
|
|
|
|
|
|
- **优点**:
|
|
|
|
|
|
- 支持字段级操作,节省内存
|
|
|
|
|
|
- 适合存储对象类型数据
|
|
|
|
|
|
- 查找速度快
|
|
|
|
|
|
- **示例**:
|
|
|
|
|
|
```
|
|
|
|
|
|
HSET realtime:stock:600519 price 1800.00 change_pct 2.50 volume 1000000
|
|
|
|
|
|
HGETALL realtime:stock:600519
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. Sorted Set
|
|
|
|
|
|
- **适用场景**:需要排序的数据,如板块动量排名
|
|
|
|
|
|
- **优点**:
|
|
|
|
|
|
- 自动排序
|
|
|
|
|
|
- 支持范围查询
|
|
|
|
|
|
- 适合Top-N查询
|
|
|
|
|
|
- **示例**:
|
|
|
|
|
|
```
|
|
|
|
|
|
ZADD sector:momentum:5:desc:20 12.5 HY001 10.2 HY002 8.7 HY003
|
|
|
|
|
|
ZRANGE sector:momentum:5:desc:20 0 9 WITHSCORES
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. List
|
|
|
|
|
|
- **适用场景**:存储有序数据,如K线数据、成分股列表
|
|
|
|
|
|
- **优点**:
|
|
|
|
|
|
- 支持顺序访问
|
|
|
|
|
|
- 适合存储时间序列数据
|
|
|
|
|
|
- 支持范围查询
|
|
|
|
|
|
- **示例**:
|
|
|
|
|
|
```
|
|
|
|
|
|
LPUSH kline:600519:1d:30 {"date":"2023-01-01","open":1700,"high":1800,"low":1650,"close":1750}
|
|
|
|
|
|
LRANGE kline:600519:1d:30 0 -1
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4. Set
|
|
|
|
|
|
- **适用场景**:存储唯一数据,如股票代码集合
|
|
|
|
|
|
- **优点**:
|
|
|
|
|
|
- 自动去重
|
|
|
|
|
|
- 支持集合操作
|
|
|
|
|
|
- 适合存储标签类数据
|
|
|
|
|
|
- **示例**:
|
|
|
|
|
|
```
|
|
|
|
|
|
SADD sector:stocks:HY001 600000 601398 601288
|
|
|
|
|
|
SMEMBERS sector:stocks:HY001
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5. String
|
|
|
|
|
|
- **适用场景**:存储任意数据,如全市场实时行情(压缩)
|
|
|
|
|
|
- **优点**:
|
|
|
|
|
|
- 灵活存储任意格式数据
|
|
|
|
|
|
- 支持二进制数据
|
|
|
|
|
|
- 适合存储大体积数据
|
|
|
|
|
|
- **示例**:
|
|
|
|
|
|
```
|
|
|
|
|
|
SET realtime:full "{compressed json data}" EX 1800
|
|
|
|
|
|
GET realtime:full
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 四、缓存策略
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 写入策略
|
|
|
|
|
|
|
|
|
|
|
|
#### 实时数据
|
|
|
|
|
|
- **主动更新**:定时任务每30秒拉取全市场数据,更新Redis
|
|
|
|
|
|
- **惰性更新**:当缓存过期时,请求触发更新
|
|
|
|
|
|
- **批量更新**:使用Pipeline批量写入,减少网络往返
|
|
|
|
|
|
|
|
|
|
|
|
#### 计算数据
|
|
|
|
|
|
- **预计算**:定时任务提前计算板块动量、技术指标等
|
|
|
|
|
|
- **按需计算**:首次请求时计算并缓存
|
|
|
|
|
|
- **增量计算**:只更新变化的数据
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 读取策略
|
|
|
|
|
|
|
|
|
|
|
|
- **优先缓存**:先从Redis读取,未命中再从数据库读取
|
|
|
|
|
|
- **缓存预热**:服务启动时预热热门数据
|
|
|
|
|
|
- **降级策略**:Redis不可用时,直接从数据库读取
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 过期策略
|
|
|
|
|
|
|
|
|
|
|
|
- **时间过期**:设置合理的过期时间
|
|
|
|
|
|
- **主动清理**:定期清理过期数据
|
|
|
|
|
|
- **内存限制**:设置Redis最大内存,使用LRU策略
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 缓存一致性
|
|
|
|
|
|
|
|
|
|
|
|
- **先更新数据库,后更新缓存**:确保数据一致性
|
|
|
|
|
|
- **缓存标记失效**:更新数据库后,标记缓存失效,下次读取时更新
|
|
|
|
|
|
- **定期全量同步**:定时全量同步数据,确保最终一致性
|
|
|
|
|
|
|
|
|
|
|
|
## 五、部署方案
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 单节点部署
|
|
|
|
|
|
- **适用场景**:开发/测试环境
|
|
|
|
|
|
- **配置**:
|
|
|
|
|
|
- 内存:4GB+
|
|
|
|
|
|
- 端口:6379
|
|
|
|
|
|
- 持久化:RDB + AOF
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 主从复制
|
|
|
|
|
|
- **适用场景**:生产环境
|
|
|
|
|
|
- **配置**:
|
|
|
|
|
|
- 主节点:负责写入
|
|
|
|
|
|
- 从节点:负责读取
|
|
|
|
|
|
- 复制方式:异步复制
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 哨兵模式
|
|
|
|
|
|
- **适用场景**:生产环境,需要高可用性
|
|
|
|
|
|
- **配置**:
|
|
|
|
|
|
- 3个哨兵节点
|
|
|
|
|
|
- 自动故障转移
|
|
|
|
|
|
- 监控主从状态
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 集群模式
|
|
|
|
|
|
- **适用场景**:大数据量场景,需要水平扩展
|
|
|
|
|
|
- **配置**:
|
|
|
|
|
|
- 3个主节点,3个从节点
|
|
|
|
|
|
- 数据分片
|
|
|
|
|
|
- 自动重平衡
|
|
|
|
|
|
|
|
|
|
|
|
## 六、性能优化
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 内存优化
|
|
|
|
|
|
- **数据压缩**:使用Redis的压缩列表
|
|
|
|
|
|
- **键空间优化**:使用哈希标签减少键冲突
|
|
|
|
|
|
- **内存淘汰策略**:设置合适的内存淘汰策略
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 网络优化
|
|
|
|
|
|
- **Pipeline**:批量执行命令,减少网络往返
|
|
|
|
|
|
- **连接池**:使用连接池管理Redis连接
|
|
|
|
|
|
- **批量操作**:使用MSET、MGET等批量命令
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 命令优化
|
|
|
|
|
|
- **使用Hash存储对象**:减少键数量
|
|
|
|
|
|
- **使用Sorted Set排序**:利用Redis内置排序
|
|
|
|
|
|
- **避免使用KEYS命令**:使用SCAN替代
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 监控与调优
|
|
|
|
|
|
- **监控指标**:
|
|
|
|
|
|
- 内存使用情况
|
|
|
|
|
|
- 命中率
|
|
|
|
|
|
- 命令执行时间
|
|
|
|
|
|
- 连接数
|
|
|
|
|
|
- **调优参数**:
|
|
|
|
|
|
- maxmemory
|
|
|
|
|
|
- maxmemory-policy
|
|
|
|
|
|
- hash-max-ziplist-entries
|
|
|
|
|
|
- hash-max-ziplist-value
|
|
|
|
|
|
|
|
|
|
|
|
## 七、缓存工具类设计
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 缓存操作接口
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
class RedisCache:
|
|
|
|
|
|
def get(self, key):
|
|
|
|
|
|
"""获取缓存"""
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def set(self, key, value, expire=None):
|
|
|
|
|
|
"""设置缓存"""
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def delete(self, key):
|
|
|
|
|
|
"""删除缓存"""
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def hash_get(self, key, field):
|
|
|
|
|
|
"""获取Hash字段"""
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def hash_set(self, key, field, value):
|
|
|
|
|
|
"""设置Hash字段"""
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def sorted_set_add(self, key, score, member):
|
|
|
|
|
|
"""添加到有序集合"""
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
def sorted_set_range(self, key, start, end, withscores=False):
|
|
|
|
|
|
"""获取有序集合范围"""
|
|
|
|
|
|
pass
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 缓存键生成器
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
class CacheKeyGenerator:
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
|
def get_stock_realtime_key(code):
|
|
|
|
|
|
return f"realtime:stock:{code}"
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
|
def get_sector_momentum_key(period, sort, order, limit):
|
|
|
|
|
|
return f"sector:momentum:{period}:{sort}:{order}:{limit}"
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
|
def get_kline_key(code, period, days):
|
|
|
|
|
|
return f"kline:{code}:{period}:{days}"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 缓存管理器
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
class CacheManager:
|
|
|
|
|
|
def __init__(self, redis_client):
|
|
|
|
|
|
self.redis = redis_client
|
|
|
|
|
|
self.key_generator = CacheKeyGenerator()
|
|
|
|
|
|
|
|
|
|
|
|
def get_stock_realtime(self, code):
|
|
|
|
|
|
"""获取股票实时行情"""
|
|
|
|
|
|
key = self.key_generator.get_stock_realtime_key(code)
|
|
|
|
|
|
return self.redis.get(key)
|
|
|
|
|
|
|
|
|
|
|
|
def set_stock_realtime(self, code, data, expire=1800):
|
|
|
|
|
|
"""设置股票实时行情"""
|
|
|
|
|
|
key = self.key_generator.get_stock_realtime_key(code)
|
|
|
|
|
|
return self.redis.set(key, data, expire)
|
|
|
|
|
|
|
|
|
|
|
|
def get_sector_momentum(self, period, sort, order, limit):
|
|
|
|
|
|
"""获取板块动量"""
|
|
|
|
|
|
key = self.key_generator.get_sector_momentum_key(period, sort, order, limit)
|
|
|
|
|
|
return self.redis.sorted_set_range(key, 0, limit-1, withscores=True)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 八、监控与告警
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 监控指标
|
|
|
|
|
|
|
|
|
|
|
|
| 指标 | 描述 | 阈值 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| 内存使用率 | Redis内存使用百分比 | >80% |
|
|
|
|
|
|
| 命中率 | 缓存命中次数/总请求次数 | <80% |
|
|
|
|
|
|
| 连接数 | 当前Redis连接数 | >1000 |
|
|
|
|
|
|
| 命令执行时间 | 平均命令执行时间 | >1ms |
|
|
|
|
|
|
| 过期键数量 | 过期键占比 | >50% |
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 告警策略
|
|
|
|
|
|
|
|
|
|
|
|
- **内存告警**:内存使用率超过80%时告警
|
|
|
|
|
|
- **命中率告警**:命中率低于80%时告警
|
|
|
|
|
|
- **连接数告警**:连接数超过1000时告警
|
|
|
|
|
|
- **错误率告警**:命令错误率超过1%时告警
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 监控工具
|
|
|
|
|
|
|
|
|
|
|
|
- **Prometheus**:收集Redis指标
|
|
|
|
|
|
- **Grafana**:可视化监控面板
|
|
|
|
|
|
- **Redis Exporter**:导出Redis指标
|
|
|
|
|
|
- **Alertmanager**:处理告警
|
|
|
|
|
|
|
|
|
|
|
|
## 九、安全考虑
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 访问控制
|
|
|
|
|
|
- **密码认证**:设置Redis密码
|
|
|
|
|
|
- **IP白名单**:限制访问IP
|
|
|
|
|
|
- **ACL**:使用Redis 6.0+的ACL功能
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 数据安全
|
|
|
|
|
|
- **数据加密**:对敏感数据进行加密
|
|
|
|
|
|
- **定期备份**:定期备份Redis数据
|
|
|
|
|
|
- **灾难恢复**:制定灾难恢复计划
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 网络安全
|
|
|
|
|
|
- **网络隔离**:Redis服务放在内网
|
|
|
|
|
|
- **SSL加密**:使用SSL加密传输
|
|
|
|
|
|
- **防火墙**:配置防火墙规则
|
|
|
|
|
|
|
|
|
|
|
|
## 十、扩展性考虑
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 数据分片
|
|
|
|
|
|
- **水平分片**:按股票代码范围分片
|
|
|
|
|
|
- **垂直分片**:按数据类型分片
|
|
|
|
|
|
- **一致性哈希**:使用一致性哈希算法
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 读写分离
|
|
|
|
|
|
- **主节点**:处理写入请求
|
|
|
|
|
|
- **从节点**:处理读取请求
|
|
|
|
|
|
- **负载均衡**:使用负载均衡器分发请求
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 集群扩展
|
|
|
|
|
|
- **自动扩缩容**:根据负载自动扩缩容
|
|
|
|
|
|
- **滚动升级**:支持无停机升级
|
|
|
|
|
|
- **跨区域部署**:支持多区域部署
|
|
|
|
|
|
|
|
|
|
|
|
## 十一、总结
|
|
|
|
|
|
|
|
|
|
|
|
Redis缓存架构设计采用多种数据结构和缓存策略,为股票分析系统提供高性能、高可靠性的数据访问层。通过合理的缓存键设计、数据结构选择和缓存策略,可以显著减少对数据源和数据库的访问,提高系统响应速度,同时保证数据的一致性和可靠性。
|
|
|
|
|
|
|
|
|
|
|
|
该设计不仅满足当前系统的需求,还为未来的扩展和优化预留了空间,能够应对数据量增长和业务需求变化的挑战。
|