Redis(Remote Dictionary Server),作为一种高性能的内存型键值数据库,广泛应用于缓存、会话管理、消息队列和排行榜等场景。本文将系统性介绍 Redis 的基础知识、安装、核心数据结构、常用命令,以及与 Java 客户端的集成,帮助开发者快速上手。
一、认识 NoSQL
Redis 属于 NoSQL 数据库,与传统的 SQL 数据库有以下显著区别:
NoSQL 数据库根据存储模型分为:
键值型:如 Redis、Memcached。
文档型:如 MongoDB。
列型:如 HBase。
图型:如 Neo4j。
二、认识 Redis
Redis 是一个 NoSQL 数据库,其主要特点是:
基于内存:支持超低延迟的读写操作。
键值存储:以 Key-Value 形式存储数据,同时支持多种 Value 数据类型。
单线程架构:采用 IO 多路复用技术实现高效并发。
支持持久化:提供 RDB 快照和 AOF 日志两种持久化方式。
分布式支持:支持主从复制、哨兵模式和分片集群。
多语言客户端:支持 Java、Python、Go 等主流编程语言。
Redis 的应用场景
缓存系统:如用户会话缓存、热点数据缓存。
排行榜:借助 SortedSet 实现分数排序。
分布式锁:通过 SetNX 和过期时间实现简单高效的分布式锁。
消息队列:利用 List 的阻塞特性模拟生产者-消费者模型。
地理位置服务:通过 Geo 类型存储地理信息。
三、Redis 安装详解
Redis 官方仅提供 Linux 环境下的安装包,本指南以 CentOS 7 为例。
1. 安装 Redis 依赖
Redis 使用 C 语言编写,需要安装 gcc
和 tcl
依赖:
yum install -y gcc tcl
2. 上传并解压安装包
将 Redis 安装包上传至服务器指定目录(如 /usr/local/src
)并解压:
tar -xzf redis-6.2.6.tar.gz
cd redis-6.2.6
make && make install
解压后,Redis 会默认安装到 /usr/local/bin
。
3. 启动 Redis
Redis 提供多种启动方式:
默认启动:前台运行,不推荐,关闭会话窗口会导致服务终止。
redis-server
指定配置文件启动:修改
redis.conf
配置后,可实现后台运行。redis-server /path/to/redis.conf
Redis主要配置:
# 允许外部访问:默认仅支持本地访问 bind 0.0.0.0 # 守护进程,修改为yes后即可后台运行 daemonize yes # 密码,设置后访问Redis必须输入密码 requirepass 123321
Redis的其他常见配置:
# 监听的端口 port 6379 # 工作目录,默认是当前目录,也就是运行redis-server时的命令,日志、持久化等文件会保存在这个目录 dir . # 数据库数量,设置为1 # 代表只使用1个库,默认有16个库,编号0~15 databases 1 # 设置redis能够使用的最大内存 maxmemory 512mb # 日志文件,默认为空,不记录日志,可以指定日志文件名 logfile "redis.log"
开机自启:通过创建系统服务文件实现:
vi /etc/systemd/system/redis.service
配置文件内容示例:
[Unit] Description=redis-server After=network.target [Service] Type=forking ExecStart=/usr/local/bin/redis-server /path/to/redis.conf PrivateTmp=true [Install] WantedBy=multi-user.target
启用服务:
systemctl daemon-reload systemctl enable redis systemctl start redis
四、Redis 的客户端工具
1. 命令行客户端
Redis 自带 redis-cli
工具,可执行交互式命令操作:
redis-cli -h 127.0.0.1 -p 6379 -a yourpassword
常见操作命令:
PING:心跳测试,服务正常返回
PONG
。SELECT:切换数据库,
SELECT 0
表示切换到第 0 号数据库。
2. 图形化客户端
Redis未提供官方图形客户端,推荐使用 RedisDesktopManager,它提供直观的操作界面:
安装包下载地址:GitHub
安装后运行
rdm.exe
,配置连接信息即可使用。
五 、Redis 的五种数据结构
Redis 提供了丰富的数据结构以适配不同场景需求,其提供了五种基本类型和一些基于基本类型衍生出来的特殊类型,这里我们先了解前五个最常用的基本类型。
Redis为了方便我们学习,将操作不同数据类型的命令也做了分组,在官网( Commands | Docs)可以查看到不同的命令,下面只讲解常用的基本命令,更多命令大家需自行查阅:
0. 通用命令
通用指令是不分数据类型的,都可以使用的指令,常见的有:
## 1. 键(key)操作相关命令
KEYS pattern # 查看符合模板的所有key, 不建议在生产环境上使用
SET key value # 设置键 key 的值为 value
GET key # 获取键 key 的值
DEL key [key ...] # 删除一个或多个键
EXISTS key [key ...] # 检查一个或多个键是否存在,返回存在键的数量
EXPIRE key seconds # 设置键的过期时间为指定的秒数
TTL key # 获取键的剩余生存时间,单位为秒
RENAME key newkey # 重命名键 key 为 newkey
TYPE key # 返回键的值类型(如 string、list、set 等)
## 2. 服务器管理命令
INFO # 获取 Redis 服务器信息和统计数据
PING # 测试服务器连通性,返回 PONG
FLUSHALL # 清空整个 Redis 数据库
FLUSHDB # 清空当前数据库中的数据
CONFIG GET parameter # 获取 Redis 配置参数
CONFIG SET parameter value # 设置 Redis 配置参数
1. String 类型
最基础的数据类型,支持字符串、整数和浮点数。 示例操作:
SET key value # 设置键值对
GET key # 获取键的值
MSET key value [key value] # 批量设置多个键值对
MGET key [key ...] # 批量获取多个键的值
INCR key # 整型键值自增 1
INCRBY key increment # 整型键值按指定步长自增
INCRBYFLOAT key increment # 浮点型键值按指定步长自增
SETNX key value # 设置键值对,仅当键不存在
SETEX key seconds value # 设置键值对并指定过期时间(秒)
应用场景:
缓存简单对象,如用户信息。
分布式计数器。
2. Hash 类型
类似 Java 的 HashMap
,支持对字段进行独立操作。 示例操作:
HSET key field value # 设置或修改 Hash 键中指定字段的值
HGET key field # 获取 Hash 键中指定字段的值
HMSET key field value [...] # 批量设置 Hash 键中多个字段的值
HMGET key field [...] # 批量获取 Hash 键中多个字段的值
HGETALL key # 获取 Hash 键中所有字段和对应的值
HKEYS key # 获取 Hash 键中的所有字段
HVALS key # 获取 Hash 键中的所有值
HINCRBY key field increment # Hash 键字段值按指定步长自增
HSETNX key field value # 设置 Hash 键字段的值,仅当字段不存在
应用场景:
存储用户信息等复杂对象。
3. List 类型
双向链表,支持正序和倒序操作。 示例操作:
LPUSH key element [...] # 向列表左侧插入一个或多个元素
LPOP key # 移除并返回列表左侧第一个元素
RPUSH key element [...] # 向列表右侧插入一个或多个元素
RPOP key # 移除并返回列表右侧第一个元素
LRANGE key start end # 获取列表指定范围内的所有元素
BLPOP key [key ...] timeout # 阻塞移除并返回左侧第一个元素,超时返回 nil
BRPOP key [key ...] timeout # 阻塞移除并返回右侧第一个元素,超时返回 nil
应用场景:
消息队列。
排队功能。
4. Set 类型
无序集合,支持去重和集合运算。 示例操作:
SADD key member [...] # 向集合中添加一个或多个元素
SREM key member [...] # 移除集合中的指定元素
SCARD key # 返回集合中元素的个数
SISMEMBER key member # 判断元素是否存在于集合中
SMEMBERS key # 获取集合中的所有元素
SINTER key1 key2 [...] # 求多个集合的交集
SDIFF key1 key2 [...] # 求多个集合的差集
SUNION key1 key2 [...] # 求多个集合的并集
应用场景:
计算共同好友、唯一访问者等。
5. SortedSet 类型
有序集合,基于 Score 排序。 示例操作:
ZADD key score member [...] # 添加或更新元素及其 score
ZREM key member [...] # 删除指定元素
ZSCORE key member # 获取指定元素的 score 值
ZRANK key member # 获取指定元素的排名(升序)
ZCARD key # 获取集合中的元素个数
ZCOUNT key min max # 统计 score 在指定范围内的元素个数
ZINCRBY key increment member # 指定元素的 score 自增
ZRANGE key start stop [WITHSCORES] # 获取指定排名范围内的元素(升序)
ZRANGEBYSCORE key min max [LIMIT offset count] # 获取指定 score 范围内的元素
ZDIFF numkeys key [key ...] # 求多个集合的差集
ZINTER numkeys key [key ...] # 求多个集合的交集
ZUNION numkeys key [key ...] # 求多个集合的并集
ZREVRANGE key start stop [WITHSCORES] # 获取指定排名范围内的元素(降序)
ZRANGEBYSCORE key max min REV # 获取指定 score 范围内的元素(降序)
应用场景:
排行榜。
带优先级的任务队列。
Redis key的最佳实践:
Redis的key允许有多个单词形成层级结构,多个单词之间用':'隔开,格式如下:
这个格式并非固定,也可以根据自己的需求来删除或添加词条。
例如我们的项目名称叫 alibaba,有user和product两种不同类型的数据,我们可以这样定义key:
user相关的key:alibaba:user:1
product相关的key:alibaba:product:1
如果Value是一个Java对象,例如一个User对象,则可以将对象序列化为JSON字符串后存储:
六、Redis 的 Java 客户端
在Redis官网中提供了各种语言的客户端,地址:Connect with Redis client API libraries | Docs。不过实际开发中,我们一般使用Spring Data Redis,其提供了不同Redis客户端的整合(Lettuce和Jedis)
1. Jedis 快速入门
Jedis的官网地址:GitHub - redis/jedis: Redis Java client, 我们先来快速入个门:
添加 Maven 依赖:
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.7.0</version> </dependency>
建立连接:
Jedis jedis = new Jedis("localhost", 6379); jedis.auth("password"); jedis.set("name", "Tiger"); System.out.println(jedis.get("name")); jedis.close();
Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此我们推荐大家使用Jedis连接池代替Jedis的直连方式。
import redis.clients.jedis.*; public class JedisConnectionFactory { private static final JedisPool jedisPool; static { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(8); // 最大连接数 config.setMaxIdle(8); // 最大空闲连接数 config.setMinIdle(0); // 最小空闲连接数 config.setMaxWaitMillis(200); // 最大等待时间(毫秒) // 初始化连接池 jedisPool = new JedisPool(config, "192.168.150.101", 6379, 1000, "123321"); } public static Jedis getJedis() { return jedisPool.getResource(); // 获取 Jedis 实例 } }
2. Spring Data Redis 快速入门
SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。并且将不同数据类型的操作API封装到了不同的类型中,官网地址:Spring Data Redis。
配置依赖:
<!-- Redis 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- Commons Pool 连接池依赖 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
配置文件:
spring: redis: host: 192.168.150.101 # Redis 主机地址 port: 6379 # Redis 端口号 password: 123321 # Redis 密码 lettuce: pool: max-active: 8 # 最大连接数 max-idle: 8 # 最大空闲连接数 min-idle: 0 # 最小空闲连接数 max-wait: 100 # 连接最大等待时间(毫秒)
使用
RedisTemplate
操作 Redis:@SpringBootTest public class RedisTest { @Autowired private RedisTemplate<String, Object> redisTemplate; @Test void testString() { // 插入和读取 string 类型数据 redisTemplate.opsForValue().set("name", "李四"); Object name = redisTemplate.opsForValue().get("name"); System.out.println("name = " + name); } }
RedisTemplate 的两种序列化实践方案
RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:
缺点:可读性差、内存占用较大
方案一:自定义 RedisTemplate
修改
RedisTemplate
的序列化器为GenericJackson2JsonRedisSerializer
。实现全局统一的序列化和反序列化规则,适用于复杂对象的存储和操作。
我们可以自定义RedisTemplate的序列化方式,代码如下:
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 设置连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 配置序列化器
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
redisTemplate.setKeySerializer(RedisSerializer.string()); // key 和 hashKey 使用 String 序列化
redisTemplate.setHashKeySerializer(RedisSerializer.string());
redisTemplate.setValueSerializer(jsonRedisSerializer); // value 和 hashValue 使用 JSON 序列化
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
return redisTemplate;
}
尽管JSON的序列化方式可以满足我们的需求,但依然存在一些问题,如图:
为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销。
方案二:使用 StringRedisTemplate
为了节省内存空间,我们并不会使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。
Spring默认提供了一个StringRedisTemplate类,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的过程:
写入 Redis 时,手动将对象序列化为 JSON。
读取 Redis 时,手动将 JSON 数据反序列化为对象。
public class RedisTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON 工具类
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testStringTemplate() throws JsonProcessingException {
// 创建 User 对象并手动序列化为 JSON
User user = new User("Java之父马士兵", 18);
String json = mapper.writeValueAsString(user);
// 写入 Redis 数据
stringRedisTemplate.opsForValue().set("user:200", json);
// 从 Redis 读取数据并反序列化
String val = stringRedisTemplate.opsForValue().get("user:200");
User user1 = mapper.readValue(val, User.class);
// 输出反序列化后的 User 对象
System.out.println("user1 = " + user1);
}
}
七、总结
Redis 是一款功能强大、性能卓越的 NoSQL 数据库,适用于多种场景。通过本指南,您可以快速掌握 Redis 的核心功能及其在 Java 开发中的应用。继续深入学习,您还可以探索 Redis 的高级特性如主从复制、哨兵模式和集群模式,打造更加高效的分布式系统。
Redis,赋能数据存储的最佳选择!
如果需要代码示例和更多高级操作,欢迎留言或查阅 Redis 官方文档!
评论