Redis基础

Redis

Redis诞生于2009年全称是Remote Dictionary Server,远程词典服务器,是一个基于内存的键值型NoSQL数据库。

Redis是一个基于内存的key-value结构非关系型数据库。

  • 基于内存存储,读写性能高
  • 适合存储热点数据(热点商品、资讯、新闻)
  • 企业应用广泛
  • 键值( key-value)型,value支持多种不同数据结构,功能丰富
  • 单线程,每个命令具备原子性
  • 低延迟,速度快(基于内存、IO多路复用、良好的编码)。
  • 支持数据持久化
  • 支持主从集群、分片集群
  • 支持多语言客户端

Redis应用场景

缓存

任务队列

消息队列

分布式锁

在Linux上安装redis

1.将Redis安装包上传到Linux

⒉.解压安装包,命令: tar -zxvf redis-4.0.0.tar.gz -C /usr/local

3.安装Redis的依赖环境gcc,命令:yum install gcc-c++

4.进入/usr/local/redis-4.0.0,进行编译,命令: make

5.进入redis的src目录,进行安装,命令: make install

启动redis

进入redis安装目录的src目录

输入命令redis-server ./redis.conf

启动redis,使用redis.conf配置文件,默认端口号6379

输入命令redis-cli -h localhost -p 6379 -a 123456

命令进入redis客户端,链接redis服务

设置redis后台运行

在redis安装目录中,修改redis.conf文件

命令vim redis.conf

找到daemoize

可使用/dae命令快速找到包括dae的行

修改no为yes

image-20230529162639817

设置redis需要密码

在redis.conf配置文件中修改

把requirepass 的注释去掉,并删除foobared

image-20230529163504813

设置redis可以远程链接

在redis.conf配置文件中修改

加上bind 127.0.0.1的注释

image-20230529164543360

redis数据类型

Redis存储的是key-value结构的数据,其中key是字符串类型,value有5种常用的数据类型:

  • 字符串string
  • 哈希hash
  • 列表list
  • 集合set
  • 有序集合sorted set
  • GEO
  • BitMap
  • HyperLog

string普通字符串,常用

hash适合存储对象

list按照插入顺序排序,可以重复元素

set无序集合,没有重复元素

sorted set有序集合,没有重复元素

redis常用命令

key的结构

在redis中,如果一个用户的id和一个商品的id都为1,那么如何区分不同类型的key?

Redis的key允许有多个单词形成层级结构,多个单词之间用’∵’隔开,格式如下:

项目名:业务名:类型:id

这个格式并非固定,也可以根据自己的需求来删除或添加词条。

例如我们的项目名称叫 heima,有user和product两种不同类型的数据,我们可以这样定义key:

  • user相关的key: heima:user:1
  • product相关的key: heima:product:1

如果Value是一个Java对象,例如一个User对象,则可以将对象序列化为JSON字符串后存储:

KEYVALUE
heima: user: 1{“id”:1,“name” : “Jack”, “age”: 21}
heima : product: 1{“id”: 1,“name” : “小米11”,“price” : 4999}

字符串string操作命令

String类型,也就是字符串类型,是Redis中最简单的存储类型。其value是字符串,不过根据字符串的格式不同,又可以分为3类:

  • string:普通字符串
  • int:整数类型,可以做自增、自减操作
  • float:浮点类型,可以做自增、自减操作

不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型的最大空间不能超过512m.

Redis中字符串类型常用命令:

大小写都行

  • SET key value 设置指定key的值
  • GET key 获取指定key的值
  • SETEX key seconds value 设置指定key的值,并将key的过期时间设为seconds秒
  • SETNX key value 只有在key不存在时设置key 的值
  • MSET 批量添加多个String类型的键值对
  • MGET 根据多个key获取多个String类型的value
  • INCR 让一个整型的key自增1
  • INCRBY 让一个整型的key自增并指定步长,例如: incrby num 2 让num值自增2
  • INCRBYFLOAT 让一个浮点类型的数字自增并指定步长

key相同的情况下,后设置的值会覆盖掉先设置的值

哈希hash操作命令

Hash类型,也叫散列,其value是一个无序字典,类似于Java中的HashMap结构

String结构是将对象序列化为JSON字符串后存储,当需要修改对象某个字段时很不方便:

Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD:

image-20230611183047339

忽略大小写

  • HSET key field value 将哈希表key 中的字段field 的值设为value
  • HGET key field 获取存储在哈希表中指定字段的值
  • HDEL key field 删除存储在哈希表中的指定字段
  • HKEYS key 获取哈希表中所有字段
  • HVALS key 获取哈希表中所有值
  • HGETALL key 获取在哈希表中指定key 的所有字段和值
  • HMSET 批量添加多个hash类型key的field的值
  • HMGET 批量获取多个hash类型key的field的值
  • HINCRBY 让一个hash类型key的字段值自增并指定步长
  • HSETNX 添加一个hash类型的key的field值,前提是这个field不存在,否则不执行

image-20230529193843261

列表list操作命令

Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。

  • 有序
  • 元素可以重复
  • 插入和删除快
  • 查询速度一般

Redis列表是简单的字符串列表,按照插入顺序排序,常用命令:

忽略大小写

  • LPUSH key value1 [value2] 将一个或多个值插入到列表头部
  • LRANGE key start stop 获取列表指定索引范围内的元素,从左开始,0~n
  • RPOP key 移除并获取列表最后一个元素
  • LPOP key 移除并返回列表左侧的第一个元素,没有则返回nil
  • LLEN key 获取列表长度
  • RPUSH key element 向列表右侧插入一个或多个元素
  • BRPOP key1 [key2 ] timeout和BLPOP … 移出并获取列表的最后一个元素或者左侧第一个,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止

image-20230612101409246

集合set操作命令

Redis set 是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据,

  • 无序
  • 元素不可重复
  • 查找快
  • 支持交集、并集、差集等功能

常用命令:

忽略大小写

  • SADD key member1 [member2] 向集合添加一个或多个成员
  • SMEMBERS key 返回集合中的所有成员
  • SISMEMBER key member 判断一个元素是否存在于set中
  • SCARD key 获取集合的成员个数
  • SINTER key1 [key2] 返回给定所有集合的交集
  • SUNION key1 [key2] 返回所有给定集合的并集
  • SDIFF key1 [key2] 返回给定所有集合的差集
  • SREM key member1 [member2] 移除集合中一个或多个成员

image-20230529195304770

有序集合sorted set操作命令

Redis sorted set有序集合是string类型元素的集合,且不允许重复的成员。每个元素都会关联一个double类型的分数(score)。redis正是通过分数来为集合中的成员进行从小到大排序。有序集合的成员是唯一的,但分数却可以重复。

常用命令:

忽略大小写

  • ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数
  • ZRANGE key start stop [WITHSCORES] 按照score排序后,获取指定排名范围内的元素,按照名次去取
  • ZINCRBY key increment member 有序集合中对指定成员的分数加上增量increment
  • ZREM key member [member …] 移除有序集合中的一个或多个成员
  • ZSCORE key member 获取sorted set中的指定元素的score值
  • ZRANK key member 获取sorted set中的指定元素的排名
  • ZCARD key 获取sorted set中的元素个数
  • ZCOUNT key min max 统计score值在给定范围内的所有元素的个数
  • ZRANGEBYSCORE key min max 按照score排序后,获取指定score范围内的元素
  • ZDIFF、ZINTER、ZUNION 求差集、交集、并集

注意:所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可,排序从索引0开始

例:ZREVRANK

image-20230529202948454

通用命令

通过help [command]可以查看一个命令的具体用法,例如:

image-20230611180253062

  • KEYS pattern 查找所有符合给定模式( pattern)的 key
  • EXISTS key 检查给定key是否存在
  • TYPE key 返回key所储存的值的类型
  • TTL key 返回给定 key的剩余生存时间(TTL, time to live),以秒为单位
  • DEL key 该命令用于在key存在是删除key
  • EXPIRE: 给一个key设置有效期,有效期到期时该key会被自动删除

如果一个key的有效期是-1,代表永久有效,-2代表已经被删除

Java中操作redis

Redis的Java客户端很多,官方推荐的有三种:

  • Jedis
  • Lettuce
  • Redisson

Spring 对Redis客户端进行了整合,提供了Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即spring-boot-starter-data-redis

Jedis

以Redis命令作为方法名称,学习成本低,简单实用。但是Jedis实例是线程不安全的,多线程环境下需要基于连接池来使用

jedis的maven坐标:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.8.0</version>
</dependency>

使用Jedis操作Redis的步骤:

1获取连接

2执行操作

3关闭连接

public static void main(String[] args) {

    //1.获取链接
    Jedis jedis = new Jedis("localhost", 6379);
	//有密码就设置密码
    //jedis.auth("123456");
    //2.执行具体操作
    String username = jedis.get("username");
    System.out.println(username);

    //3.关闭链接
    jedis.close();
}

Jedis连接池的用法

public class JedisConnectionFaction {

    private static final JedisPool jedisPool;

    static {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //设置最大连接数
        jedisPoolConfig.setMaxTotal(8);
        //设置最大空闲链接
        jedisPoolConfig.setMaxIdle(8);
        //设置最小空闲链接
        jedisPoolConfig.setMinIdle(0);
        //设置等待时长
        jedisPoolConfig.setMaxWaitMillis(1000);

        jedisPool = new JedisPool(jedisPoolConfig,"localhost"
                ,6379,1000);
    }

    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}

Spring Data Redis

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis

  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)
  • 提供了RedisTemplate统一API来操作Redis
  • 支持Redis的发布订阅模型
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
  • 支持基于Redis的JDKCollection实现

在Spring Boot项目中,可以使用Spring Data Redis来简化Redis操作,maven坐标:

<!--redis依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!--连接池依赖-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

Spring Data Redis中提供了一个高度封装的类:RedisTemplate,针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:

API返回值类型说明
redisTemplate.opsForValue()ValueOperations操作String类型数据
redisTemplate.opsForHash()HashOperations操作Hash类型数据
redisTemplate.opsForList()ListOperations操作List类型数据
redisTemplate.opsForSet()SetOperations操作Set类型数据
redisTemplate.opsForZSet()ZSetOperations操作SortedSet类型数据
redisTemplate通用的命令

application.yml文件中的配置

server:
  port: 8080
spring:
  application:
    name: reggie_take_out
  # redis 相关配置
  redis:
    host: localhost
    port: 6379
    # password: 123456 如果设置密码,就使用
    database: 0
    jedis:
      # redis连接池配置
      pool:
        max-active: 8 # 最大连接数
        max-wait: 1ms # 连接池最大阻塞等待时间
        max-idle: 4 # 连接池中的最大空闲链接
        min-idle: 0 # 连接池中的最小空闲连接

先注入redisTemplate

@Autowired
private RedisTemplate redisTemplate;

操作String类型的数据

//操作String类型的数据
@Test
public void testString(){
    //获得valueOptions
    ValueOperations valueOperations = redisTemplate.opsForValue();

    //利用valueOperations来操作
    valueOperations.set("city123","beijing");

    //设置键值及超时时间
    valueOperations.set("key1","value1",10l, TimeUnit.SECONDS);

    String city123 = (String) valueOperations.get("city123");

    String value1 = (String) valueOperations.get("value1");

    System.out.println(value1);
    System.out.println(city123);
    System.out.println("-------------------------------");
}

操作Hash类型的数据

//操作Hash类型的数据
@Test
public void testHash(){
    //获得操作hash类型的对象
    HashOperations hashOperations = redisTemplate.opsForHash();

    hashOperations.put("001","name","胡大头");
    hashOperations.put("001","age","18");

    String name = (String) hashOperations.get("001", "name");
    String age = (String) hashOperations.get("001", "age");

    //获得hash结构中的所有字段
    Set keys = hashOperations.keys("001");
    for (Object key : keys) {
        System.out.print(key + "  ");
    }
    System.out.println();

    //获得hash结构中的所有的值
    List values = hashOperations.values("001");
    for (Object value : values) {
        System.out.print(value + "  ");
    }
    System.out.println();

    System.out.println(name);
    System.out.println(age);
    System.out.println("-------------------------------");
}

操作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);
    }

    System.out.println("-------------------------------");

    //出队列
    Long size = listOperations.size("myList");
    int intValue = size.intValue();
    for (int i = 0; i < intValue; i++) {
        String o = (String) listOperations.rightPop("myList");
        System.out.println(o);
    }
    System.out.println("------------------------------------");
}//操作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.print(value + "  ");
    }

    System.out.println();
    System.out.println("-------------------------------");
}

操作Set类型的数据

//操作set类型的数据
@Test
public void testSet(){
    SetOperations setOperations = redisTemplate.opsForSet();

    //存值
    setOperations.add("mySet","a","b","c","d","b");

    //取值
    Set mySet = setOperations.members("mySet");
    for (Object o : mySet) {
        System.out.println(o);
    }
    System.out.println("-------------------------------");

    //删除成员
    setOperations.remove("mySet","a","c");

    //取值
    mySet = setOperations.members("mySet");
    for (Object o : mySet) {
        System.out.println(o);
    }

}

操作ZSet类型的数据

//操作ZSet类型的数据
@Test
public void testZSet(){
    ZSetOperations zSetOperations = redisTemplate.opsForZSet();

    //存值
    zSetOperations.add("myZSet","a",10);
    zSetOperations.add("myZSet","b",11);
    zSetOperations.add("myZSet","c",12);
    zSetOperations.add("myZSet","d",13);
    zSetOperations.add("myZSet","e",14);
    //取值
    Set<String> myZSet = zSetOperations.range("myZSet", 0, -1);
    for (String s : myZSet) {
        System.out.println(s);
    }
    System.out.println("------------------------");
    //修改分数
    zSetOperations.incrementScore("myZSet","a",10);
    //删除成员
    zSetOperations.remove("myZSet","b","e");

    myZSet = zSetOperations.range("myZSet", 0, -1);
    for (String s : myZSet) {
        System.out.println(s);
    }
    System.out.println("------------------------");
}

通用的操作

//通用的操作
@Test
public void testCommon(){
    //获取redis中所有的key
    Set<String> keys = redisTemplate.keys("*");
    for (String key : keys) {
        System.out.println(key);
    }
    System.out.println("-----------------");
    //判断某个key是否存在
    Boolean itcast = redisTemplate.hasKey("itcast");
    System.out.println(itcast);
    System.out.println("-----------------");
    //删除指定key
    redisTemplate.delete("myHash");
    //获取指定key对应的value数据类型
    DataType myZSet = redisTemplate.type("myZSet");
    System.out.println(myZSet.name());
    System.out.println("-----------------");
}

SpringDataRedis的序列化方式

RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:

image-20230612114622476

可读性差,内存占用较大

我们可以自定义RedisTemplate的序列化方式

需要引入Jackson的依赖

<!--Jackson-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        //创建redisTemplate对象
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        //设置链接工厂
        redisTemplate.setConnectionFactory(connectionFactory);
        //默认的Key序列化器为:JdkSerializationRedisSerializer
        // key序列化
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        // value序列化
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        return redisTemplate;
    }
}

注意:在注入redisTemplate对象的时候,也要指定对应的泛型

为了在反序列化时知道对象的类型,JSON序列化器会将类的class类型写入json结果中,存入Redis,会带来额外的内存开销。

image-20230612120930539

为了节省内存空间,我们并不会使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。

Spring默认提供了一个StringRedisTemplate类,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的过程:

在注入的时候,直接注入StringRedisTemplate即可

@Autowired
private StringRedisTemplate stringRedisTemplate;

//序列化器,可以使用其他的 
private static final ObjectMapper mapper = new ObjectMapper();

@Test
public void testObject() throws JsonProcessingException {
    //创建对象
    User user = new User();
    user.setName("胡大头");
    user.setSex("男");
    //手动序列化
    String json = mapper.writeValueAsString(user);
    stringRedisTemplate.opsForValue().set("user:100",json);
    //获取数据
    String s = stringRedisTemplate.opsForValue().get("user:100");
    //手动反序列化
    User readValue = mapper.readValue(s, User.class);
    System.out.println(readValue);

}

这种序列化方式不需要自定义redis的配置类配置序列化方式。但是需要手动序列化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于学习Redis基础知识,可以按照以下思路进行学习: 1. 了解Redis的概念和特点:首先需要了解Redis是什么,它的主要特点是什么,它为什么被广泛应用于缓存、消息队列、会话管理等场景。 2. 安装和配置Redis:根据你的操作系统,安装Redis并进行相关配置。可以参考Redis官方文档或其他教程来完成这一步。 3. 学习Redis的数据结构:Redis支持多种数据结构,如字符串、哈希、列表、集合和有序集合等。了解每种数据结构的特点、用途和操作命令,并通过实际操作来加深理解。 4. 掌握Redis的常用命令:学习Redis的常用命令,如get、set、hget、hset、lpush、lrange、sadd、smembers等,了解每个命令的具体用法和参数含义。 5. 理解Redis的持久化机制:了解Redis的RDB和AOF两种持久化方式,以及它们的优缺点。学习如何进行备份和恢复数据。 6. 学习Redis的事务和Lua脚本:了解Redis事务的基本概念和使用方法,以及如何使用Lua脚本来进行复杂的操作。 7. 深入了解Redis的性能优化和高可用方案:学习如何优化Redis的性能,包括配置调优、使用合适的数据结构、合理地使用缓存等。同时了解Redis的高可用方案,如主从复制、哨兵模式和集群模式。 8. 学习Redis与其他技术的结合:了解Redis如何与其他技术进行结合,如与Python、Java等编程语言的配合使用,以及与Spring、Django等框架的整合。 以上是学习Redis基础知识的一个思路,你可以根据自己的实际情况和需求进行学习和拓展。推荐参考一些经典的Redis教程和实战案例,通过实际操作和项目实践来提升自己的技能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值