京东app下载平台娄底地seo
Redis基础知识
一、Redis简介
1.1 什么是Redis?
Redis是一个开源的、基于内存的数据结构存储系统,可以用作:
- 数据库
- 缓存
- 消息中间件
- 分布式锁
1.2 Redis特点
- 高性能:基于内存操作
- 支持多种数据结构
- 支持数据持久化
- 支持主从复制
- 支持事务
- 支持Lua脚本
1.3 应用场景
- 缓存
- 计数器
- 排行榜
- 消息队列
- 分布式锁
- 会话管理
二、Redis安装与配置
2.1 安装Redis
# Windows安装
# 1. 下载Redis for Windows
# 2. 运行安装程序
# 3. 配置环境变量# Linux安装
sudo apt-get update
sudo apt-get install redis-server# Mac安装
brew install redis
2.2 启动Redis
# Windows启动
redis-server# Linux启动
sudo systemctl start redis-server# Mac启动
brew services start redis
2.3 连接Redis
# 命令行连接
redis-cli# 指定主机和端口连接
redis-cli -h localhost -p 6379# 使用密码连接
redis-cli -a password
三、Redis数据类型
3.1 字符串(String)
# 设置值
SET key value# 获取值
GET key# 设置过期时间
SETEX key seconds value# 批量设置
MSET key1 value1 key2 value2# 批量获取
MGET key1 key2# 递增
INCR key# 递减
DECR key
3.2 哈希(Hash)
# 设置字段值
HSET key field value# 获取字段值
HGET key field# 获取所有字段
HGETALL key# 删除字段
HDEL key field# 判断字段是否存在
HEXISTS key field
3.3 列表(List)
# 左侧插入
LPUSH key value# 右侧插入
RPUSH key value# 左侧弹出
LPOP key# 右侧弹出
RPOP key# 获取列表范围
LRANGE key start stop# 获取列表长度
LLEN key
3.4 集合(Set)
# 添加元素
SADD key member# 删除元素
SREM key member# 获取所有元素
SMEMBERS key# 判断元素是否存在
SISMEMBER key member# 获取集合大小
SCARD key
3.5 有序集合(Sorted Set)
# 添加元素
ZADD key score member# 删除元素
ZREM key member# 获取分数范围内的元素
ZRANGEBYSCORE key min max# 获取排名
ZRANK key member# 获取分数
ZSCORE key member
四、Redis高级特性
4.1 事务
# 开始事务
MULTI# 执行命令
SET key1 value1
SET key2 value2# 提交事务
EXEC# 取消事务
DISCARD
4.2 发布订阅
# 订阅频道
SUBSCRIBE channel# 发布消息
PUBLISH channel message# 取消订阅
UNSUBSCRIBE channel
4.3 持久化
# RDB持久化配置
save 900 1
save 300 10
save 60 10000# AOF持久化配置
appendonly yes
appendfsync everysec
五、Redis集群
5.1 主从复制
# 配置从节点
SLAVEOF master_ip master_port# 查看复制状态
INFO replication
5.2 哨兵模式
# 启动哨兵
redis-sentinel sentinel.conf# 哨兵配置
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
5.3 集群模式
# 创建集群
redis-cli --cluster create node1:6379 node2:6379 node3:6379# 添加节点
redis-cli --cluster add-node new_node:6379 existing_node:6379
六、Redis性能优化
6.1 内存优化
- 使用适当的数据类型
- 设置过期时间
- 使用压缩
- 定期清理
6.2 配置优化
# redis.conf
maxmemory 2gb
maxmemory-policy allkeys-lru
appendonly yes
appendfsync everysec
6.3 监控
# 查看内存使用
INFO memory# 查看客户端连接
INFO clients# 查看命令统计
INFO commandstats
七、Redis安全
7.1 访问控制
# 设置密码
CONFIG SET requirepass password# 修改密码
AUTH old_password new_password
7.2 网络安全
# redis.conf
bind 127.0.0.1
protected-mode yes
八、Redis最佳实践
8.1 开发规范
-
键名设计
- 使用有意义的名称
- 使用冒号分隔
- 控制键名长度
-
数据设计
- 合理使用数据类型
- 避免大key
- 设置过期时间
-
性能优化
- 使用pipeline
- 使用连接池
- 避免频繁操作
8.2 运维规范
-
监控
- 监控内存使用
- 监控连接数
- 监控命令执行
-
备份
- 定期备份数据
- 测试恢复流程
- 保存备份记录
-
安全
- 启用密码认证
- 限制网络访问
- 定期更新密码
九、Redis与Java集成
9.1 Jedis客户端
// 添加Jedis依赖
// Maven
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version>
</dependency>// Gradle
implementation 'redis.clients:jedis:4.3.1'
9.2 基本操作示例
// 创建Jedis客户端
Jedis jedis = new Jedis("localhost", 6379);// 设置密码(如果有)
jedis.auth("password");// 字符串操作
jedis.set("key", "value");
String value = jedis.get("key");// 哈希操作
jedis.hset("user:1", "name", "张三");
jedis.hset("user:1", "age", "25");
Map<String, String> user = jedis.hgetAll("user:1");// 列表操作
jedis.lpush("messages", "消息1");
jedis.lpush("messages", "消息2");
List<String> messages = jedis.lrange("messages", 0, -1);// 集合操作
jedis.sadd("tags", "Java", "Redis", "Spring");
Set<String> tags = jedis.smembers("tags");// 有序集合操作
jedis.zadd("scores", 89.5, "张三");
jedis.zadd("scores", 92.0, "李四");
Set<String> topScores = jedis.zrevrange("scores", 0, 1);// 关闭连接
jedis.close();
9.3 使用连接池
// 创建连接池配置
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(8);
poolConfig.setMaxIdle(8);
poolConfig.setMinIdle(0);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);
poolConfig.setMinEvictableIdleTimeMillis(60000);
poolConfig.setTimeBetweenEvictionRunsMillis(30000);
poolConfig.setNumTestsPerEvictionRun(3);
poolConfig.setBlockWhenExhausted(true);// 创建连接池
JedisPool jedisPool = new JedisPool(poolConfig, "localhost", 6379, 2000, "password");// 从连接池获取连接
try (Jedis jedis = jedisPool.getResource()) {// 使用Jedis进行操作jedis.set("key", "value");String value = jedis.get("key");
}// 关闭连接池
jedisPool.close();
9.4 使用Pipeline批量操作
Jedis jedis = new Jedis("localhost", 6379);
Pipeline pipeline = jedis.pipelined();// 批量设置
for (int i = 0; i < 1000; i++) {pipeline.set("key:" + i, "value:" + i);
}// 执行Pipeline
pipeline.sync();// 关闭连接
jedis.close();
十、Redis与Spring Boot集成
10.1 添加Spring Data Redis依赖
<!-- Maven -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency><!-- Gradle -->
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
10.2 配置Redis连接
# application.yml
spring:redis:host: localhostport: 6379password: passworddatabase: 0timeout: 10000lettuce:pool:max-active: 8max-wait: -1max-idle: 8min-idle: 0
10.3 创建Redis配置类
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);// 使用Jackson2JsonRedisSerializer序列化值Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);ObjectMapper mapper = new ObjectMapper();mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);serializer.setObjectMapper(mapper);// 设置key和value的序列化规则template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(serializer);template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(serializer);template.afterPropertiesSet();return template;}
}
10.4 使用RedisTemplate
@Service
public class UserService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;// 存储用户信息public void saveUser(String id, User user) {redisTemplate.opsForValue().set("user:" + id, user);}// 获取用户信息public User getUser(String id) {return (User) redisTemplate.opsForValue().get("user:" + id);}// 删除用户信息public void deleteUser(String id) {redisTemplate.delete("user:" + id);}// 设置过期时间public void setExpire(String key, long timeout, TimeUnit unit) {redisTemplate.expire(key, timeout, unit);}
}
10.5 使用RedisRepository
@RedisHash("users")
public class User {@Idprivate String id;private String name;private int age;// 构造函数、getter和setter方法
}@Repository
public interface UserRepository extends CrudRepository<User, String> {List<User> findByAge(int age);List<User> findByNameStartingWith(String prefix);
}
十一、Redis与Docker部署
11.1 使用Docker运行Redis
# 拉取Redis镜像
docker pull redis:latest# 运行Redis容器
docker run -d --name redis -p 6379:6379 redis:latest# 运行Redis容器(带数据持久化)
docker run -d --name redis -p 6379:6379 -v /data/redis:/data redis:latest# 运行Redis容器(带密码)
docker run -d --name redis -p 6379:6379 redis:latest redis-server --requirepass password
11.2 使用Docker Compose部署Redis
# docker-compose.yml
version: '3'
services:redis:image: redis:latestcontainer_name: redisports:- "6379:6379"volumes:- ./data:/datacommand: redis-server --requirepass passwordnetworks:- redis-networkredis-commander:image: rediscommander/redis-commander:latestcontainer_name: redis-commanderports:- "8081:8081"environment:- REDIS_HOSTS=local:redis:6379:0:passworddepends_on:- redisnetworks:- redis-networknetworks:redis-network:driver: bridge
11.3 使用Docker部署Redis集群
# docker-compose-cluster.yml
version: '3'
services:redis1:image: redis:latestcontainer_name: redis1command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yesports:- "6371:6379"volumes:- ./data1:/datanetworks:- redis-cluster-networkredis2:image: redis:latestcontainer_name: redis2command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yesports:- "6372:6379"volumes:- ./data2:/datanetworks:- redis-cluster-networkredis3:image: redis:latestcontainer_name: redis3command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yesports:- "6373:6379"volumes:- ./data3:/datanetworks:- redis-cluster-networkredis4:image: redis:latestcontainer_name: redis4command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yesports:- "6374:6379"volumes:- ./data4:/datanetworks:- redis-cluster-networkredis5:image: redis:latestcontainer_name: redis5command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yesports:- "6375:6379"volumes:- ./data5:/datanetworks:- redis-cluster-networkredis6:image: redis:latestcontainer_name: redis6command: redis-server --port 6379 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yesports:- "6376:6379"volumes:- ./data6:/datanetworks:- redis-cluster-networknetworks:redis-cluster-network:driver: bridge
# 创建Redis集群
docker exec -it redis1 redis-cli --cluster create \redis1:6379 redis2:6379 redis3:6379 redis4:6379 redis5:6379 redis6:6379 \--cluster-replicas 1
十二、Redis常见问题解答
12.1 内存问题
问题: Redis内存占用过高
解决方案:
- 设置最大内存限制:
CONFIG SET maxmemory 2gb
- 配置内存淘汰策略:
CONFIG SET maxmemory-policy allkeys-lru
- 使用适当的数据类型,避免大key
- 设置过期时间,让不常用的数据自动过期
- 使用压缩算法减少内存占用
12.2 性能问题
问题: Redis响应慢
解决方案:
- 检查是否有慢查询:
SLOWLOG GET 10
- 优化数据结构,避免使用大key
- 使用Pipeline批量操作
- 增加Redis实例,使用集群分散负载
- 检查网络延迟和带宽
12.3 连接问题
问题: 客户端连接Redis失败
解决方案:
- 检查Redis服务是否正在运行
- 检查防火墙设置,确保端口6379开放
- 检查Redis配置文件中的bind设置
- 如果使用密码,确保密码正确
- 检查客户端连接池配置
12.4 数据一致性问题
问题: 主从复制数据不一致
解决方案:
- 检查主从复制状态:
INFO replication
- 检查网络连接是否稳定
- 如果从节点落后太多,考虑重新同步
- 使用哨兵模式自动处理故障转移
- 考虑使用Redis集群提高可用性
12.5 持久化问题
问题: Redis重启后数据丢失
解决方案:
- 启用RDB持久化:
CONFIG SET save "900 1 300 10 60 10000"
- 启用AOF持久化:
CONFIG SET appendonly yes
- 配置AOF同步策略:
CONFIG SET appendfsync everysec
- 定期备份数据文件
- 测试恢复流程确保数据可以正确恢复
十三、Redis高级应用场景
13.1 分布式锁
// 使用Redis实现分布式锁
public class RedisLock {private RedisTemplate<String, String> redisTemplate;private String lockKey;public RedisLock(RedisTemplate<String, String> redisTemplate, String lockKey) {this.redisTemplate = redisTemplate;this.lockKey = lockKey;}public boolean tryLock(String requestId, long expireTime) {return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, expireTime, TimeUnit.MILLISECONDS));}public boolean releaseLock(String requestId) {String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +"return redis.call('del', KEYS[1]) else return 0 end";return Boolean.TRUE.equals(redisTemplate.execute(new DefaultRedisScript<>(script, Boolean.class), Collections.singletonList(lockKey), requestId));}
}// 使用示例
String requestId = UUID.randomUUID().toString();
RedisLock lock = new RedisLock(redisTemplate, "lock:resource");
try {if (lock.tryLock(requestId, 30000)) {// 获取锁成功,执行业务逻辑// ...} else {// 获取锁失败}
} finally {// 释放锁lock.releaseLock(requestId);
}
13.2 限流器
// 使用Redis实现限流器
public class RedisRateLimiter {private RedisTemplate<String, String> redisTemplate;private String key;private int limit;private int period;public RedisRateLimiter(RedisTemplate<String, String> redisTemplate, String key, int limit, int period) {this.redisTemplate = redisTemplate;this.key = key;this.limit = limit;this.period = period;}public boolean tryAcquire() {String script = "local current = redis.call('incr', KEYS[1]) " +"if current == 1 then " +"redis.call('expire', KEYS[1], ARGV[1]) " +"end " +"return current <= tonumber(ARGV[2])";return Boolean.TRUE.equals(redisTemplate.execute(new DefaultRedisScript<>(script, Boolean.class), Collections.singletonList(key), String.valueOf(period), String.valueOf(limit)));}
}// 使用示例
RedisRateLimiter limiter = new RedisRateLimiter(redisTemplate, "rate:api", 100, 60);
if (limiter.tryAcquire()) {// 允许请求通过// ...
} else {// 请求被限流
}
13.3 排行榜
// 使用Redis实现排行榜
public class RedisLeaderboard {private RedisTemplate<String, String> redisTemplate;private String key;public RedisLeaderboard(RedisTemplate<String, String> redisTemplate, String key) {this.redisTemplate = redisTemplate;this.key = key;}public void addScore(String member, double score) {redisTemplate.opsForZSet().add(key, member, score);}public List<String> getTopMembers(int count) {return new ArrayList<>(redisTemplate.opsForZSet().reverseRange(key, 0, count - 1));}public List<String> getTopMembersWithScores(int count) {Set<ZSetOperations.TypedTuple<String>> tuples = redisTemplate.opsForZSet().reverseRangeWithScores(key, 0, count - 1);List<String> result = new ArrayList<>();for (ZSetOperations.TypedTuple<String> tuple : tuples) {result.add(tuple.getValue() + ":" + tuple.getScore());}return result;}public Long getRank(String member) {return redisTemplate.opsForZSet().reverseRank(key, member);}
}// 使用示例
RedisLeaderboard leaderboard = new RedisLeaderboard(redisTemplate, "leaderboard:game");
leaderboard.addScore("player1", 100);
leaderboard.addScore("player2", 200);
leaderboard.addScore("player3", 150);
List<String> topPlayers = leaderboard.getTopMembers(3);
// 结果: [player2, player3, player1]
13.4 消息队列
// 使用Redis实现消息队列
public class RedisMessageQueue {private RedisTemplate<String, String> redisTemplate;private String queueKey;public RedisMessageQueue(RedisTemplate<String, String> redisTemplate, String queueKey) {this.redisTemplate = redisTemplate;this.queueKey = queueKey;}public void push(String message) {redisTemplate.opsForList().rightPush(queueKey, message);}public String pop() {return redisTemplate.opsForList().leftPop(queueKey);}public String popWithTimeout(long timeout, TimeUnit unit) {return redisTemplate.opsForList().leftPop(queueKey, timeout, unit);}public long size() {return redisTemplate.opsForList().size(queueKey);}
}// 生产者
RedisMessageQueue queue = new RedisMessageQueue(redisTemplate, "queue:messages");
queue.push("消息1");
queue.push("消息2");// 消费者
while (true) {String message = queue.popWithTimeout(1, TimeUnit.SECONDS);if (message != null) {// 处理消息// ...}
}
13.5 缓存策略
// 使用Redis实现缓存策略
public class RedisCache {private RedisTemplate<String, Object> redisTemplate;private long defaultExpire;public RedisCache(RedisTemplate<String, Object> redisTemplate, long defaultExpire) {this.redisTemplate = redisTemplate;this.defaultExpire = defaultExpire;}public <T> T get(String key, Class<T> clazz) {return (T) redisTemplate.opsForValue().get(key);}public void set(String key, Object value) {set(key, value, defaultExpire);}public void set(String key, Object value, long expire) {redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);}public void delete(String key) {redisTemplate.delete(key);}public <T> T getOrSet(String key, Supplier<T> supplier, Class<T> clazz) {return getOrSet(key, supplier, defaultExpire, clazz);}public <T> T getOrSet(String key, Supplier<T> supplier, long expire, Class<T> clazz) {T value = get(key, clazz);if (value == null) {value = supplier.get();set(key, value, expire);}return value;}
}// 使用示例
RedisCache cache = new RedisCache(redisTemplate, 3600);
User user = cache.getOrSet("user:1", () -> userService.findById(1), User.class);
十四、Redis最佳实践总结
14.1 键名设计最佳实践
-
命名规范
- 使用冒号分隔不同部分:
业务:类型:ID
- 使用小写字母
- 避免使用特殊字符
- 控制键名长度
- 使用冒号分隔不同部分:
-
常见模式
- 用户信息:
user:1
- 用户会话:
session:abc123
- 计数器:
counter:pageviews
- 排行榜:
leaderboard:game
- 缓存:
cache:product:1
- 用户信息:
14.2 数据类型选择最佳实践
-
字符串(String)
- 适用于简单数据:计数器、缓存、会话ID
- 可以存储序列化的对象(JSON、二进制)
-
哈希(Hash)
- 适用于对象属性:用户信息、产品详情
- 可以部分更新,节省内存
-
列表(List)
- 适用于有序集合:消息队列、最新动态
- 可以实现分页
-
集合(Set)
- 适用于无序唯一集合:标签、关注者
- 支持集合运算:交集、并集、差集
-
有序集合(Sorted Set)
- 适用于排序集合:排行榜、权重队列
- 支持范围查询和排序
14.3 性能优化最佳实践
-
内存优化
- 使用适当的数据类型
- 避免大key(超过10KB)
- 设置过期时间
- 使用压缩算法
-
查询优化
- 使用Pipeline批量操作
- 使用连接池
- 避免频繁操作
- 使用适当的命令(如HGETALL替代多次HGET)
-
配置优化
- 调整内存限制和淘汰策略
- 配置持久化策略
- 调整连接池大小
- 启用慢查询日志
14.4 高可用最佳实践
-
主从复制
- 至少配置一个从节点
- 监控复制状态
- 定期备份数据
-
哨兵模式
- 至少配置三个哨兵节点
- 配置合理的故障检测参数
- 测试故障转移流程
-
集群模式
- 至少配置三个主节点和三个从节点
- 合理分配槽位
- 监控集群状态
14.5 安全最佳实践
-
访问控制
- 设置强密码
- 限制命令执行权限
- 定期更新密码
-
网络安全
- 限制IP访问
- 使用SSL/TLS加密
- 禁用危险命令
-
数据安全
- 定期备份数据
- 加密敏感数据
- 实施数据访问控制