目录
Redis 入门
什么是 Redis?
Redis 是一个基于内存的 key-value 结构数据库。
① 基于内存存储,读写性能高
② 适合存储热点数据(热点商品、咨询、新闻)
③ 企业应用广泛
Redis 简介
The open source, in-memory data store used by millions of developers as a database, cache, streaming engine, and message broker.
Redis 是一个 开源的内存中的数据结构存储系统,它可以用作:数据库、缓存和消息中间件。
官网:https://redis.io/
Redis 是用 C 语言开发的一个开源的高性能键值对(key-value) 数据库,官方提供的数据是可以达到 100000+ 的 QPS (每秒内查询次数)。它存储的 value 类型比较丰富,也被称为结构化的 NoSql 数据库。
NoSql (Not Only SQL),不仅仅是 SQL 。泛指非关系型数据库。 NoSQL 数据库并不是要取代关系型数据库,而是关系型数据库的补充。
- 关系型数据库 (RDBMS)
- MySql
- Oracle
- DB2
- SQLServer
- 非关系型数据库 (NoSql)
- Redis
- Mongo db
- MemCached
⮞ Redis 应用场景
① 缓存
② 任务队列
③ 消息队列
④ 分布式锁
Redis 下载与安装
Redis 安装包分为 windows 和 Linux 版:
① Windows 版下载地址:https://github.com/microsoftarchive/redis/releases
② Linux 版下载地址:
https://download.redis.io/releases/
在 Linux 系统安装 Redis 步骤:
① 将 Redis 安装包上传到 Linux
② 解压安装包,命令 tar -zxvf redis-4.0.0.tar.gz -C /usr/local
③ 安装 Redis 的依赖环境 gcc, 命令 : yum install gcc-c++
④ 进入 /usr/local/redis-4.0.0, 进行编译,命令:make
⑤ 进入 redis 的 src 目录,进行安装,命令:make install
Redis 的 Windows 版属于绿色软件,直接解压即可使用,解压后目录结构如下:
Redis 服务启动与停止
Linux 中 Redis 服务启动,可以使用 redis-server, 默认端口号为 6379。
客户端:
Ctrl + C 停止 Redis 服务。
让 Redis 在后台运行:
Windows 中 Redis 服务启动, 直接双击即可:
Ctrl + C 停止 Redis 服务。
客户端:
问题 1 :默认情况下不需要用户名和密码。
修改 redis.conf 配置文件,设置需要密码:
重新启动 redis 服务:
问题 2:Redis 服务启动时默认是不允许远程连接的:
修改 redis.conf:
重启 redis 服务:
关闭防火墙:
可以远程连接了:
Redis 数据类型
介绍
Redis 存储的是 key-value 结构的数据,其中 key 是字符串类型,value 有 5 种常见的数据结构。
① 字符串 string
② 哈希 hash
③ 列表 list
④ 集合 set
⑤ 有序集合 sorted set
Redis 常用命令
字符串 string 操作命令
Redis 中字符串类型常用命令:
① SET key value 设置指定 key 的值
② GET key 获取指定 key 的值
③ SETEX key seconds value 设置指定 key 的值,并将 key 的过期时间设为 seconds 秒
④ SETNX key value 只有在 key 不存在时设置 key 的值
更多命令可以参考 Redis 中文网:
https://www.redis.net.cn/
哈希 hash 操作命令
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合于存储对象,常用命令:
① HSET key field value 将哈希表 key 中字段 field 的值设置为 value
② HGET key field 获取存储在哈希表中指定字段的值
③ HDEL key field 删除存储在哈希表中的指定字段
④ HKEYS key 获取哈希表中的所有字段
⑤ HVALS key 获取哈希表中的所有值
⑥ HGETALL key 获取在哈希表中指定 key 的所有字段和值
列表 list 操作命令
Redis 列表是简单的字符串列表,按照插入顺序排序 (注意列表可以有重复元素!),常用命令:
① LPUSH key value1 [value2] 将一个或多个值插入到列表头部
② LRANGE key start stop 获取列表指定范围内的元素
③ RPOP key 移除并获取列表最后一个元素
④ LLEN key 获取列表长度
⑤ BRPOP key1 [key2] timeout 移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
集合 set 操作命令
Redis set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据,常用命令:
① SADD key member1 [member2] 向集合添加一个或多个成员
② SMEMBERS key 返回集合中的所有成员
③ SCARD key 返回集合的成员数
④ SINTER key1 [key2] 返回给定所有集合的交集
⑤ SUNION key1 [key2] 返回给定所有集合的并集
⑥ SDIFF key1 [key2] 返回给定所有集合的差集
⑦ SREM key member1 [member2] 移除集合中一个或多个成员
有序集合 sorted set 操作命令
Redis sorted set 有序集合是 string 类型元素的集合,且不允许重复的成员。每个元素都会关联一个 double 类型的分数(score) 。Redis 正是通过分数来对集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数却可以重复。常用命令:
① ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数
② ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合中指定区间内的成员
③ ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment
④ ZREM key member[member…] 移除有序集合中一个或多个成员
通用命令
① KEYS pattern 查找所有符合给定模式 (pattern) 的 key
② EXISTS key 检查给定 key 是否存在
③ TYPE key 返回 key 所存储的值的类型
④ TTL key 返回给定 key 的剩余生存时间 (TTL, time to live) 以秒为单位
⑤ DEL key 在 key 存在时删除 key
在 Java 中操作 Redis
介绍
Redis 的 Java 客户端有很多,官方推荐的有三种:
① Jedis
② Lettuce
③ Redisson
Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis, 在 SpringBoot 项目中还提供了对应的 starter, 即 spring-boot-starter-data-redis。
Jedis
Jedis 的 maven 坐标:
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.0</version> </dependency>
使用 Jedis 操作 Redis 的步骤:
① 获取连接
② 执行操作
③ 关闭连接
Spring Data Redis
在 SpringBoot 项目中,可以使用 Spring Data Redis 来简化 Redis 操作,maven 坐标:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
Spring Data Redis 中提供了一个高度封装的类:RedisTemplate, 针对 jedis 客户端中大量 api 进行了归类封装,将同一类型操作封装为 operation 接口,具体分类如下:
① ValueOperations :简单 K-V 操作
② SetOperations : set 类型数据操作
③ ZSetOperations : zset 类型数据操作
④ HashOperations : 针对 map 类型的数据操作
⑤ ListOperations : 针对 list 类型的数据操作
新建 springdataredis_demo 项目:
App.java:
application.yml:
SpringDataRedisTest:
操作 String 类型数据
编写方法测试:
设置序列化器 (RedisConfig) :
@Configuration public class RedisConfig extends CachingConfigurerSupport { @Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>(); // 默认的 Key 序列化器为:JdkSerializationRedisSerializer redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setConnectionFactory(connectionFactory); return redisTemplate; } }
/** * 操作 String 类型数据 */ @Test public void testString() { redisTemplate.opsForValue().set("city", "beijing"); String value = (String) redisTemplate.opsForValue().get("city"); System.out.println(value); redisTemplate.opsForValue().set("key1", "value1", 10l, TimeUnit.SECONDS); Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("city", "shenzhen"); System.out.println(aBoolean); }
操作 Hash 类型数据
/** * 操作 Hash 类型数据 */ @Test public void testHash() { HashOperations hashOperations = redisTemplate.opsForHash(); // 存值 hashOperations.put("002", "name", "xiaoming"); hashOperations.put("002", "age", 20); hashOperations.put("002", "address", "bj"); // 取值 Integer age = (Integer) hashOperations.get("002", "age"); System.out.println(age); // 获取 hash 结构中的所有字段 Set keys = hashOperations.keys("002"); for (Object key : keys) { System.out.println(key); } // 获得 hash 结构中所有值 List values = hashOperations.values("002"); for (Object value : values) { System.out.println(value); } }
操作 List 类型数据
/** * 操作 List 类型的数据 */ @Test public void testList() { ListOperations listOperations = redisTemplate.opsForList(); // 存值 listOperations.leftPush("mylist", "a"); listOperations.leftPushAll("mylist", "b", "c", "d"); // 取值 List<String> mylist = listOperations.range("mylist", 0, -1); for (String value : mylist) { System.out.println(value); } // 获得列表长度 llen Long size = listOperations.size("mylist"); int lSize = size.intValue(); for (int i = 0; i < lSize; i++) { // 出队列 String element = (String) listOperations.rightPop("mylist"); System.out.println(element); } }
操作 Set 类型数据
/** * 操作 Set 类型的数据 */ @Test public void testSet() { SetOperations setOperations = redisTemplate.opsForSet(); // 存值 setOperations.add("myset", "a", "b", "c", "a"); // 取值 Set<String> myset = setOperations.members("myset"); for (String o : myset) { System.out.println(o); } // 删除成员 setOperations.remove("myset", "a", "b"); // 取值 myset = setOperations.members("myset"); for (String o : myset) { System.out.println(o); } }
操作 ZSet 类型数据
/** * 操作 ZSet 类型的数据 */ @Test public void testZset() { ZSetOperations zSetOperations = redisTemplate.opsForZSet(); // 存值 zSetOperations.add("myZset", "a", 10.0); zSetOperations.add("myZset", "b", 11.0); zSetOperations.add("myZset", "c", 12.0); zSetOperations.add("myZset", "a", 13.0); // 取值 Set<String> myZset = zSetOperations.range("myZset", 0, -1); for (String s : myZset) { System.out.println(s); } // 修改分数 zSetOperations.incrementScore("myZset", "b", 20.0); // 取值 myZset = zSetOperations.range("myZset", 0, -1); for (String s : myZset) { System.out.println(s); } // 删除成员 zSetOperations.remove("myZset", "a", "b"); // 取值 myZset = zSetOperations.range("myZset", 0, -1); for (String s : myZset) { System.out.println(s); } }
通用操作
/** * 通用操作,针对不同的数据类型都可以操作 */ @Test public void testCommon() { // 获取 Redis 中所有的 key Set<String> keys = redisTemplate.keys("*"); for (String key : keys) { System.out.println(key); } // 判断某个 key 是否存在 Boolean myset = redisTemplate.hasKey("myset"); System.out.println(myset); // 删除指定 key redisTemplate.delete("myset"); myset = redisTemplate.hasKey("myset"); System.out.println(myset); // 获取指定 key 对应的 value 的数据类型 DataType dataType = redisTemplate.type("myhash"); System.out.println(dataType.name()); }
完整测试代码
@SpringBootTest @RunWith(SpringRunner.class) public class SpringDataRedisTest { @Autowired private RedisTemplate redisTemplate; /** * 操作 String 类型数据 */ @Test public void testString() { redisTemplate.opsForValue().set("city", "beijing"); String value = (String) redisTemplate.opsForValue().get("city"); System.out.println(value); redisTemplate.opsForValue().set("key1", "value1", 10l, TimeUnit.SECONDS); Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("city", "shenzhen"); System.out.println(aBoolean); } /** * 操作 Hash 类型数据 */ @Test public void testHash() { HashOperations hashOperations = redisTemplate.opsForHash(); // 存值 hashOperations.put("002", "name", "xiaoming"); hashOperations.put("002", "age", 20); hashOperations.put("002", "address", "bj"); // 取值 Integer age = (Integer) hashOperations.get("002", "age"); System.out.println(age); // 获取 hash 结构中的所有字段 Set keys = hashOperations.keys("002"); for (Object key : keys) { System.out.println(key); } // 获得 hash 结构中所有值 List values = hashOperations.values("002"); for (Object value : values) { System.out.println(value); } } /** * 操作 List 类型的数据 */ @Test public void testList() { ListOperations listOperations = redisTemplate.opsForList(); // 存值 listOperations.leftPush("mylist", "a"); listOperations.leftPushAll("mylist", "b", "c", "d"); // 取值 List<String> mylist = listOperations.range("mylist", 0, -1); for (String value : mylist) { System.out.println(value); } // 获得列表长度 llen Long size = listOperations.size("mylist"); int lSize = size.intValue(); for (int i = 0; i < lSize; i++) { // 出队列 String element = (String) listOperations.rightPop("mylist"); System.out.println(element); } } /** * 操作 Set 类型的数据 */ @Test public void testSet() { SetOperations setOperations = redisTemplate.opsForSet(); // 存值 setOperations.add("myset", "a", "b", "c", "a"); // 取值 Set<String> myset = setOperations.members("myset"); for (String o : myset) { System.out.println(o); } // 删除成员 setOperations.remove("myset", "a", "b"); // 取值 myset = setOperations.members("myset"); for (String o : myset) { System.out.println(o); } } /** * 操作 ZSet 类型的数据 */ @Test public void testZset() { ZSetOperations zSetOperations = redisTemplate.opsForZSet(); // 存值 zSetOperations.add("myZset", "a", 10.0); zSetOperations.add("myZset", "b", 11.0); zSetOperations.add("myZset", "c", 12.0); zSetOperations.add("myZset", "a", 13.0); // 取值 Set<String> myZset = zSetOperations.range("myZset", 0, -1); for (String s : myZset) { System.out.println(s); } // 修改分数 zSetOperations.incrementScore("myZset", "b", 20.0); // 取值 myZset = zSetOperations.range("myZset", 0, -1); for (String s : myZset) { System.out.println(s); } // 删除成员 zSetOperations.remove("myZset", "a", "b"); // 取值 myZset = zSetOperations.range("myZset", 0, -1); for (String s : myZset) { System.out.println(s); } } /** * 通用操作,针对不同的数据类型都可以操作 */ @Test public void testCommon() { // 获取 Redis 中所有的 key Set<String> keys = redisTemplate.keys("*"); for (String key : keys) { System.out.println(key); } // 判断某个 key 是否存在 Boolean myset = redisTemplate.hasKey("myset"); System.out.println(myset); // 删除指定 key redisTemplate.delete("myset"); myset = redisTemplate.hasKey("myset"); System.out.println(myset); // 获取指定 key 对应的 value 的数据类型 DataType dataType = redisTemplate.type("myhash"); System.out.println(dataType.name()); } }