redis入门

  • 内存数据库: Redis是基于内存的key-value结构数据库,数据存储在内存中而非磁盘
  • 高性能: 由于数据存储在内存中,读写性能极高
  • 键值存储: 采用key-value结构存储数据,如:id:101name:小智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 有序集合中对指定成员的分数加上增量 increment
  • ZREM 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项目集成

操作步骤

  1. 导入Spring Data Redis 的maven坐标
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 配置Redis数据源
spring:
  redis:
    host: localhost
    port: 6379
    password:

还可以通过database:指定数据库(默认会创建16个数据库)

  1. 编写配置类,创建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的序列化器以确保存储的值也能正确序列化。
  1. 通过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);  
    }  
}