随笔 - 49  文章 - 0  评论 - 0  阅读 - 2259

Redis

Redis

1.认识redis

1.1什么是NoSQL

NoSQL是非关系数据库

  • 数据结构:非结构化
  • 数据关联:非关联的
  • 查询方式:非SQL查询
  • 事务特性:BASE(无法满足事务的ACID)

使用场景

  • 数据结构不固定的
  • 对一致性,安全性要求不高
  • 对性能有要求

1.2什么是Redis

Redis是一个基于内存的键值型NoSQL数据库

特征

  • 键值:支持多种不同的数据结构功能丰富
  • 单线程,每个命令具备原子性
  • 低延迟,速度快(基于内存,IO多路复用,良好的编码)
  • 支持数据持久化
  • 支持主从集群,分片集群
  • 支持多语言客户端

2.Redis常见命令

2.1Redis数据结构

Redis是一个key-value的数据库,key一般是String类型,value的类型多种多样

value基本类型

  • String 字符串
  • Hash hash表
  • List 有序集合(链表)
  • Set 无序集合
  • SortedSet 可排序集合

2.2Redis通用命令

通用命令是指部分数据类型都可以使用的命令

  • KEYS:查看所有符合模板的key(**支持模糊查询,通配符为* **)
  • DEL:删除一个指定的key
  • EXISTS:判断key是否存在
  • EXPIRE:给一个可以设置有效起,有效期到期时该key自动删除
  • TTL:查看一个key的剩余有效期

2.3String类型

String是字符串类型,是Redis最简单的一种存储类型,其value是字符串

根据字符串格式分为三类:

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

无论是哪种类型,底层都是字节数组形式储存,只是编码方式不同,最大空间不能超过512m

2.3.1String类型常用命令

常见命令

  • SET:添加或修改一个String类型的键值对
  • GET:根据key获取String类型的value
  • MSET:批量添加键值对
  • MGET:根据多个key获取多个String类型的value
  • INCR:让一个整形的key自增11
  • INCRBY:让一个整形的key自增并指定长度
  • INCRBYFLOAT:让一个浮点类型数字自增并指定长度
  • SETNX:添加一个String类型的键值对,前提是key不存在,否则不执行
  • SETEX:添加一个String类型的键值对,指定有效期

思考

Redis作为一个非关系型数据库是没有Table的,如何区分不同类型的key?

可以使用key的分级存储用:

例如:

2.4Hash类型

hash类型,也叫散列,value是一个无序字典

String结构是将对象序列化成josn字符串后存储,当需要修改某个对象字段时很不方便
Hash结构可以将对象中每个字段独立存储,可以对单个字段做CRUD

2.4.1Hash类型常用命令

常用命令

2.5List类型

Redis中的List类型与java中的LinkedList类似,可以看作一个双向链表的结构,支持正向检索,也支持反向检索

2.5.1List常用命令

常用命令

思考

2.6Set类型

Redis中的Set结构与java中的HashSet类似,可以看作是一个没有value的HashMap

2.6.1Set常用命令

常用命令

image

2.7SortedSet类型

Redis是一个可排序的Set集合,底层结构中Sorted每一个元素都有一个score属性,基于score属性对元素进行排序,底层实现是一个跳表(SkipList)加Hash表.跳表用作排序

2.7.1SortedSet常见命令

常见命令

3.Redis的Java客户端

3.1Jedis客户端

3.1.1Jedis快速入门

快速入门

  • 1.引入依赖
<dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.7.0</version>
        </dependency>
  • 2.建立连接
 @BeforeEach
    void  setUp(){
        //建立连接
        jedis= new Jedis("192.168.41.128",6379);
        //设置密码\
        jedis.auth("123321");
        //选择库
        jedis.select(0);
    }
  • 3.测试
  @Test
    void testString(){
        //存入数据
        String result=jedis.set("name","虎哥");
        System.out.println("result = " + result);
        //获取数据
        String name = jedis.get("name");
        System.out.println("name = " + name);
    }
    @Test
    void testHash(){
        //存入hash数据
        jedis.hset("user:1","name","Jack");
        jedis.hset("user:1","age","20");
        //获取hash数据
        Map<String, String> usr1 = jedis.hgetAll("user:1");
        System.out.println("usr1 = " + usr1);

    }
  • 4.释放资源
@AfterEach
    void tearDown(){
        if (jedis!=null){
            jedis.close();
        }
    }

注意:需要开启redis服务端,关闭防火墙

3.1.2Jedis连接池

Jedis本身线程是不安全的,并且频繁的创建何销毁连接会有性能损耗,因此推荐使用jedis连接池来代替jedis直连方式.

创建jedis连接池

public class JedisConnectionFactory {
    private static final JedisPool jedisPool;
    static {
        //配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(8);
        poolConfig.setMaxIdle(8);
        poolConfig.setMinIdle(0);
        poolConfig.setMaxWaitMillis(1000);
        //创建连接池对象
        jedisPool = new JedisPool(poolConfig,"192.168.41.128",6379,1000,"123321");

    }
    //返回jedis对象
    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}
 @BeforeEach
    void  setUp(){
        //建立连接
//        jedis= new Jedis("192.168.41.128",6379);
        //连接池中获取jedis
        jedis= JedisConnectionFactory.getJedis();
        //设置密码\
        jedis.auth("123321");
        //选择库
        jedis.select(0);
    }

需要注意的是使用连接池中的jedis释放资源时不会直接释放掉,而是将其放回连接池中

3.2SpringDateRedis

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

3.2.1SpringDateRedis快速入门

SpringDateRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作,并且将不同数据类型的操作API封装到不同的类型中:

快速入门

  • 1.引入依赖
 <!-- 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>
  • 2.配置文件
spring:
 redis:
   host: 192.168.41.128
   port: 6379
   password: 123321
   lettuce:
     pool:
       max-active: 8 #最大连接
       max-idle: 8 #最大空闲
       min-idle: 0 #最小空闲
       max-wait: 100 #连接最大空闲时间  
  • 3.注入RedisTemplate
@Autowired(required = false)
   private RedisTemplate redisTemplate;
  • 4.编写测试
    @Test
    void testString(){
        redisTemplate.opsForValue().set("name","子路");
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name = " + name);
    }  

3.2.2SpringDateRedis的序列化方式

RedisTemplate可以接收任意Objet最为值写入Redis,但是jdk默认的序列化方式是将Object

按字符数组形式写.

缺点:

  • 可读性差
  • 占用内存

所以需要自定义RedisTemplate序列化方式

编写一个配置类,自定义Redis序列化方式

@Bean
   public RedisTemplate<String,Object> redisTemplate(  RedisConnectionFactory connectionFactory){
       //创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //设置连接工厂
        template.setConnectionFactory(connectionFactory);
        //创建josn序列化工具
         GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
         //设置key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        //设置value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        template.afterPropertiesSet();
        //返回
        return template;
    }

创建User对象

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private String name;
    private Integer age;
}

更改注入依赖的泛型

  @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Test
    void testString(){
        redisTemplate.opsForValue().set("name","子路");
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name = " + name);
    }
   @Test
    void User(){
        redisTemplate.opsForValue().set("user",new User("zlsame ",24));
       User zlsame = (User) redisTemplate.opsForValue().get("user");
       System.out.println("zlsame = " + zlsame);



   }

3.2.3使用StringRedisTemplate手动序列化

思考

所以为了节省内存空间,我们并不会使用自动序列化和反序列化,当我们要存储对象时,会手动完成序列化和反序列化

 @Autowired
    private StringRedisTemplate stringRedisTemplate;
    private static final ObjectMapper mapper =new ObjectMapper();
    @Test
    void testString() {
        stringRedisTemplate.opsForValue().set("name", "子路");
        Object name = stringRedisTemplate.opsForValue().get("name");
        System.out.println("name = " + name);
    }

    @Test
    void User() throws JsonProcessingException {
        //创建对象
        User user = new User("zlsame ", 24);
        //手动序列化
        String josn = mapper.writeValueAsString(user);
        //写入数据
        stringRedisTemplate.opsForValue().set("user:001",josn);
        //获取数据
        String o = stringRedisTemplate.opsForValue().get("user:001");
        //手动反序列化
        User user1 = mapper.readValue(o,User.class);
        System.out.println("user1 = " + user1);


    }
posted on   zl子路  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示