redis入门
- 内存数据库: Redis是基于内存的key-value结构数据库,数据存储在内存中而非磁盘
- 高性能: 由于数据存储在内存中,读写性能极高
- 键值存储: 采用key-value结构存储数据,如:
id:101、name:小智、city:北京 - 应用场景: 适合存储热点数据(热点商品、资讯、新闻),企业应用广泛
应用场景
- 热点数据: 秒杀、抢购等短时间内大量用户访问的数据
- 性能优势: 相比MySQL能承受更高的并发访问量
- 内存限制: 不能存储所有数据,只适合存储访问量大的热点数据
redis常用数据类型
- 存储结构: Redis采用key-value结构存储数据,其中key必须是字符串类型,value支持5种常用数据类型
- 五种类型:
- 字符串(string)
- 哈希(hash)
- 列表(list)
- 集合(set)
- 有序集合(sorted set/zset)
常用命令
字符串操作
- SET命令:设置指定key的值,格式为SET key value,key和value之间用空格隔开。相当于向Redis插入一条数据。
- GET命令:获取指定key的值,格式为GET key。如果key不存在则返回null。
- SETEX命令:设置key的值并指定过期时间,格式为SETEX key seconds value,seconds单位为秒。常用于短信验证码等需要自动过期的场景。
- SETNX命令:仅当key不存在时设置值,格式为SETNX key value。如果key已存在则不设置,常用于分布式锁等场景。
哈希操作
- HSET:
- 功能:设置哈希表key中字段field的值
- 语法:HSET key field value
- 示例:HSET 100 name xiaoming表示在key为100的哈希表中设置name字段值为xiaoming
- HGET:
- 功能:获取哈希表中指定字段的值
- 语法:HGET key field
- 示例:HGET 100 name返回xiaoming
- HDEL:
- 功能:删除哈希表中指定字段
- 语法:HDEL key field
- 示例:HDEL 100 name会删除name字段
- HKEYS:
- 功能:获取哈希表中所有字段名
- 语法:HKEYS key
- 示例:HKEYS 100返回
[name, age]
- HVALS:
- 功能:获取哈希表中所有字段值
- 语法:HVALS key
- 示例:HVALS 100返回
[xiaoming, 22]
列表操作
- 数据结构: Redis列表是简单的字符串列表,按照插入顺序排序
- 元素特性: 列表中的每个元素都是简单的字符串,如abcd等
- 可视化理解: 可以想象为水平摆放的队列,左侧为头部,右侧为尾部
1)LPUSH命令
- 功能: 将一个或多个值插入到列表头部
- 语法:
LPUSH key value1 [value2...] - 方向说明: 命令中的L代表left(左侧),从列表左侧插入数据
- 多值插入: 可以一次性插入多个值,用空格分隔
- 插入顺序: 后插入的元素会排在更靠近头部的位置
2)LRANGE命令
- 功能: 获取列表中指定范围内的元素
- 语法:
LRANGE key start stop - 范围参数:
- 0表示第一个元素(头部)
- -1表示最后一个元素(尾部)
- 类似SQL的分页查询
- 全量查询: LRANGE key 0 -1可获取全部元素
3)RPOP命令
- 功能: 从列表右侧移除并返回一个元素
- 语法: RPOP key
- 返回值: 返回被移除的元素值
- 删除效果: 每次执行会减少列表长度
4)LLEN命令
- 功能: 获取列表的长度(元素个数)
- 语法: LLEN key
- 返回值: 返回当前列表中的元素数量
集合操作
SADD
- 功能:向集合添加一个或多个成员
- 语法:
SADD key member1 [member2...] - 特点:
- 命令前缀”s”代表set类型
- 插入顺序与存储顺序无关(无序性)
- 插入已存在元素会返回0且不执行操作
- 示例:
- sadd set1 a b c d 成功返回4
- sadd set1 a 返回0(元素已存在)
SMEMBERS
- 功能:返回集合中所有成员
- 语法:SMEMBERS key
- 特点:
- 返回结果不保证顺序
- 实际查询结果可能与插入顺序不同
- 示例:
- smembers set1 返回d b a c(顺序随机)
SCARD
- 功能:获取集合成员数量
- 语法:SCARD key
- 示例:
- scard set1 返回4(集合有4个元素)
SINTER
- 功能:返回多个集合的交集
- 语法:SINTER key1 [key2…]
- 运算规则:返回所有集合共有的元素
- 示例:
- set1={a,b,c,d}, set2={a,b,x,y}
- sinter set1 set2 返回a b
SUNION
- 功能:返回多个集合的并集
- 语法:SUNION key1 [key2…]
- 运算规则:合并所有集合元素并去重
- 示例:
- set1={a,b,c,d}, set2={a,b,x,y}
- sunion set1 set2 返回d a b c x y
SREM
- 功能:删除集合中一个或多个成员
- 语法:SREM key member1 [member2…]
- 特点:
- 可同时删除多个元素
- 返回成功删除的元素数量
- 示例:
- srem set1 a 返回1(成功删除)
- 删除后smembers set1显示b c d
有序集合操作
- 有序集合定义:Redis中string类型元素的集合,不允许重复元素。
- 有序集合特点:每个元素关联一个分数,用于排序。
- 有序集合结构:包含key和value,value为带分数的元素集合。
- 排序依据:通过元素的分数值进行排序,如a:0.1,b:3.0,e:2.5。
- 与普通集合区别:有序集合通过分数排序,普通集合无序。
ZADD key score1 member1 [score2 member2]向有序集合添加一个或多个成员ZRANGE key start stop [WITHSCORES]通过索引区间返回有序集合中指定区间内的成员ZINCRBY key increment member有序集合中对指定成员的分数加上增量 incrementZREM key member [member ...]移除有序集合中的一个或多个成员
通用命令
- 定义: 不分数据类型的命令,可以操作所有Redis键值对
- 特点: 与具体数据类型无关,主要针对key进行操作
- 包含命令: KEYS、EXISTS、TYPE、DEL
keys pattern
- 功能: 查找所有符合给定模式(pattern)的key
- 模式语法:
-
- 匹配所有key
- set* 匹配以”set”开头的key
-
- 示例:
- keys * 返回数据库所有key
- keys set* 返回以”set”开头的key(set1, set2等)
exists key
- 功能: 检查给定key是否存在
- 返回值:
- 1 表示key存在
- 0 表示key不存在
- 示例:
- exists name 返回1(存在)
- exists abc 返回0(不存在)
type key
- 功能: 返回key所储存值的类型
- 常见返回值:
- string(字符串)
- set(集合)
- list(列表)
- 示例:
- type name 返回”string”
- type set1 返回”set”
- type mylist 返回”list”
del key
- 功能: 删除指定的key
- 特点:
- 可以一次删除多个key
- 删除后key立即从数据库中消失
- 示例:
- del name 删除name键
- del set1 set2 zset1 同时删除三个键
Java中操作Redis
Spring Data Redis使用方式
- Spring生态: 是Spring框架的一部分,对Jedis和Lettuce进行了高度封装
- 简化操作: 使用起来比原生客户端更加简单,适合Spring项目集成
操作步骤
- 导入Spring Data Redis 的maven坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>- 配置Redis数据源
spring:
redis:
host: localhost
port: 6379
password:还可以通过database:指定数据库(默认会创建16个数据库)
- 编写配置类,创建RedisTemplate对象
@Configuration
@Slf4j
public class RedisConfiguration {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
log.info("开始创建RedisTemplate对象...");
RedisTemplate redisTemplate = new RedisTemplate();
// 设置redis连接工厂对象
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 设置redis的key序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
}Info
- 通过setConnectionFactory方法设置Redis连接工厂
- 通过setKeySerializer设置key的序列化方式为StringRedisSerializer,这样可以确保存储到Redis中的key是可读的字符串格式
- RedisTemplate是Spring Data Redis提供的一个核心类,用于简化Redis的数据操作。通过这个配置,应用程序可以通过RedisTemplate与Redis数据库进行交互,执行各种Redis命令。
- 目前这个配置只设置了key的序列化器,通常还会设置value的序列化器以确保存储的值也能正确序列化。
- 通过RedisTemplate对象操作Redis
字符串
@Test
public void testString(){
// set get setex setnx
redisTemplate.opsForValue().set("name", "张三");
System.out.println(redisTemplate.opsForValue().get("name"));
redisTemplate.opsForValue().set("code","1234",3, TimeUnit.MINUTES);
// setnx
redisTemplate.opsForValue().setIfAbsent("lock", "1");
// setnx
redisTemplate.opsForValue().setIfAbsent("lock", "2");
}哈希
@Test
public void testHash() {
// hset hget hdel hkeys hvals
HashOperations hashOperations = redisTemplate.opsForHash();
hashOperations.put("100", "name", "张三");
hashOperations.put("100", "age", 18);
System.out.println(hashOperations.get("100", "name"));
System.out.println(hashOperations.get("100", "age"));
System.out.println(hashOperations.keys("100"));
System.out.println(hashOperations.values("100"));
hashOperations.delete("100", "age");
System.out.println(hashOperations.keys("100"));
System.out.println(hashOperations.values("100"));
}张三
18
[age, name]
[18, 张三]
[name]
[张三]列表
@Test
public void testList() {
// lpush lpop rpush rpop
ListOperations listOperations = redisTemplate.opsForList();
listOperations.leftPushAll("list", "1", "2", "3", "4", "5");
listOperations.leftPush("list", "6");
List mylist = listOperations.range("list", 0, -1);
System.out.println(mylist);
listOperations.rightPop("list");
Long size = listOperations.size("list");
System.out.println(size);
}[6, 5, 4, 3, 2, 1]
5集合
@Test
public void testSet(){
//sadd smembers scard sinter sunion srem
SetOperations setOperations = redisTemplate.opsForSet();
setOperations.add("set1","a","b","c","d");
setOperations.add("set2","a","b","x","y");
Set members = setOperations.members("set1");
System.out.println(members);
Long size = setOperations.size("set1");
System.out.println(size);
Set intersect = setOperations.intersect("set1", "set2");
System.out.println(intersect);
Set union = setOperations.union("set1", "set2");
System.out.println(union);
setOperations.remove("set1","a","b");
}[a, b, c, d]
4
[a, b]
[a, b, c, d, x, y]有序集合
@Test
public void testZset() {
//zadd zrange zincrby zrem
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
zSetOperations.add("zset1", "a", 10);
zSetOperations.add("zset1", "b", 12);
zSetOperations.add("zset1", "c", 9);
Set zset1 = zSetOperations.range("zset1", 0, -1);
System.out.println(zset1);
zSetOperations.incrementScore("zset1", "c", 10);
zSetOperations.remove("zset1", "a", "b");
}[c, a, b]通用操作
@Test
public void testCommon(){
//keys exists type del
Set keys = redisTemplate.keys("*");
System.out.println(keys);
Boolean name = redisTemplate.hasKey("name");
Boolean set1 = redisTemplate.hasKey("set1");
for (Object key : keys) {
DataType type = redisTemplate.type(key);
System.out.println(type.name());
}
redisTemplate.delete("mylist");
}店铺营业状态设置
@RestController("AdminShopController")
@RequestMapping("/admin/shop")
@Api(tags = "店铺相关接口")
@Slf4j
public class ShopController {
@Autowired
private RedisTemplate redisTemplate;
public static final String KEY = "SHOP_STATUS";
@PutMapping("/{status}")
@ApiOperation("设置营业状态")
/**
* 设置营业状态
* @param status
* @return
*/
public Result setStatus(@PathVariable Integer status) {
log.info("设置店铺营业状态:{}", status == 1 ? "营业中" : "打烊中");
redisTemplate.opsForValue().set(KEY, status);
return Result.success();
}
/**
* 获取营业状态
*
* @return
*/
@GetMapping("/status")
@ApiOperation("获取营业状态")
public Result<Integer> getStatus() {
Integer status = (Integer) redisTemplate.opsForValue().get(KEY);
log.info("获取店铺营业状态:{}", status == 1 ? "营业中" : "打烊中");
return Result.success(status);
}
}