首页 > 数据库 >Redis

Redis

时间:2022-11-17 01:34:52浏览次数:58  
标签:String Redis key 类型 序列化 name

Redis

SQL:关系型数据库

NoSQL:非关系型数据库

image-20221112160510291

1. 初识redis

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

Redis特征:

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

2. Redis命令

2.1Redis通用命令

通用指令是部分数据类型的,都可以使用的指令,常见的有:

  • KEYS:查看符合模板的所有key,不建议在生产环境设备上指定;

  • DEL:删除一个指定的KEY;

  • EXISTS:判断key是否存在;

  • EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除;

  • TTL:查看一个key的剩余有效期;

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

​ help keys;

2.2 String类型

String类型,也就是字符串类型,是Redis中最简单的存储类型;

其value是字符串,不过根据字符串的格式不同,又可以分为3类:

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

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

image-20221113223704390

String类型的常见命令

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

2.3 Redis的key的结构

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

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

image-20221113232234358

2.4 Hash类型

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

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

image-20221113233235810

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

image-20221113233411052

Hash类型的常见命令:

  • HSET key field value: 添加或修改hash类型key的field的值;
  • HGET key field: 获取一个hash类型key的field的值;
  • HMSET: 批量添加多个hash类型key的field的值;
  • HMGET: 批量获取多个hash类型key的field的值;
  • HGETALL:获取一个hash类型的key中的所有的field和value;
  • HKEYS:获取一个hash类型的key中的所有的field;
  • HVALS:获取一个hash类型的key中的所有的value;
  • HINCRBY:让一个hash类型key的字段值自增并指定步长;
  • HSETNX:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行;

2.5 List类型

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

特征也与LinkedList类似:

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

常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等;

List的常见命令

  • LPUSH key element ...:向列表左侧插入一个或多个元素;
  • LPOP key:移除并返回列表左侧的第一个元素,没有则返回nil;
  • RPUSH key element ...:向列表右侧插入一个或多个元素;
  • RPOP key:移除并返回列表右侧的第一个元素;
  • LRANGE key star end:返回一段角标范围内的所有元素;
  • BLPOP和BRPOP:与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil;

image-20221114004457534

思考:

如何利用List结构模拟一个栈?

  • 入口和出口在同一边

如何利用List结构模拟一个栈?

  • 入口和出口在不同边

如何利用List结构模拟一个阻塞队列?

  • 入口和出口在不同边
  • 出队时采用BLPOP或BRPOP

2.6 Set类型

Redis的Set结构与java中HashSet类似,可以看做是一个value为null的HashMap,因为也是一个hash表,具备与hashSet类似的特征:

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

Set类型的常见命令有:

  • SADD key member ... :想set中添加一个或多个元素;

  • SREM key member ... :移除set中的指定元素;

  • SCARD key:返回set中元素的个数;

  • SISMEMBER key member:判断一个元素是否存在于set中;

  • SMEMBERS: 获取set中的所有元素;

  • SINTER key1 key2 ... :求key1与key2的交集;

  • SDIFF key1 key2 ... :求key1与key2的差集;

  • SUNION key1 key2... : 求key1和key2的并集;

2.7 SortedSet类型

Redis的SortedSet是一个可排序的set集合,与java中的TreeSet有些类似,但底层数据结构却差别很大,SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加hash表.

SortedSet具备下列特性:

  • 可排序
  • 元素不重复
  • 查询速度快

因为SortedSet的可排序性,经常被用来实现排行榜这样的功能;

SortedSet的常用命令:

  • ZADD key score member:添加一个或多个元素到sorted set,如果已经存在则更新其score值;
  • ZREM key member:删除sorted set中的一个指定元素;
  • ZSCORE key member:获取sorted set中的指定元素的score值;
  • ZRANK key member:获取sorted set中的指定元素的排名;
  • ZCARD key:获取sorted set中的元素个数;
  • ZCOUNT key min max:统计score值在给定范围内的所有元素的个数;
  • ZINCRBY key increment member:让sorted set 中的指定元素自增,步长为指定的increment值;
  • ZRANGE key min max;按照score排序后,获取指定排名范围内的元素;
  • ZRANGEBYSCORE key min max:按照score排序后,获取指定score范围内的元素;
  • ZDIFF,ZINTTER,ZUNION:求差集,交集,并集

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

3. Redis的java客户端

image-20221114151625368

3.1 Jedis

Jedis的官网地址: https://github.com/redis/jedis

3.1.1 jedis使用的基本步骤

  1. 引入依赖

    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>4.3.0</version>
    </dependency>
    
  2. 创建Jedis对象,建立连接

private Jedis jedis;

@BeforeEach
void setUp() {
    //建立连接
    jedis = new Jedis("192.168.17.128", 6379);
    //设置密码
    jedis.auth("123456");
    //选择库
    jedis.select(0);
}
  1. 使用Jedis,方法名与Redis命令一致;
//测试String
@Test
void testString() {
    //存入数据
    String result = jedis.set("name", "虎哥");
    System.out.println("result=" + result);
    //获取数据
    String name = jedis.get("name");
    System.out.println("name=" + name);
}
  1. 释放资源
@AfterEach
void tearDown() {
    if (jedis != null) {
        jedis.close();
    }
}

3.1.2 Jedis连接池

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

public class JedisConnectionFactory {
    private static final JedisPool jedisPool;

    static {
        //配置连接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        //设置最大连接
        poolConfig.setMaxTotal(8);
        //最大空闲连接
        poolConfig.setMaxIdle(8);
        //最小空闲连接
        poolConfig.setMaxIdle(0);
        //设置最长等待事件,ms
        poolConfig.setMaxWaitMillis(1000);
        //创建连接池对象
        jedisPool = new JedisPool(poolConfig, "192.168.17.128", 6379, 1000, "123456");
    }
    //获取jedis对象
    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}

3.2 SpringDataRedis

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis,官网地址:https://spring.io/projects/spring-data-redis

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

3.2.1 SpringDataRedis快速入门

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

image-20221114191559325

SpringBoot已经提供了对SpringDataRedis的支持,使用非常简单:

  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>
  1. 在application.yml配置redis信息
spring:
  redis:
    host: 192.168.17.128
    port: 6379
    password: 123456
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: 100
  1. 注入RedisTemplate
@Autowired
private RedisTemplate redisTemplate;
  1. 编写测试
@Test
void contextLoads() {
    //插入一条String类型数据
    redisTemplate.opsForValue().set("name", "大哥哥");
    //读取一条String类型数据
    Object name = redisTemplate.opsForValue().get("name");
    System.out.println("name:"+name);
}

3.2.2 SpringDataRedis的序列化方式

RedisTemplate可以接收任意Object作为值写入Redis,只不过写入钱会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是:\xAC\xED\x00\x05t\x00 \xE5\xA4\xA7\xE5\x93\xA5\xE5\x93\xA5

缺点:1. 可读性差 2.内存占用较大

我们可以自定义RedisTemplate的序列化方式,代码如下:

@Configuration
public class RedisConfig {

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

尽管JSON的序列方式可以满足我们的需求,但任然存在一些问题,如图:

image-20221115000505484

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

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

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

@SpringBootTest
class RedisStringTests {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    void contextLoads() {
        //插入一条String类型数据
        stringRedisTemplate.opsForValue().set("name", "大哥哥");
        //读取一条String类型数据
        Object name = stringRedisTemplate.opsForValue().get("name");
        System.out.println("name:" + name);
    }

    private static final ObjectMapper mapper = new ObjectMapper();

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

    }

    @Test
    void testHash() {
        stringRedisTemplate.opsForHash().put("user:400", "name", "wz小哥哥");
        stringRedisTemplate.opsForHash().put("user:400", "age", "18");

        Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:400");
        System.out.println("entries=" + entries);

    }    
}

3.2.3 RedisTemplate的两种序列化实践方案:

方案一:

  1. 自定义RedisTemplate;
  2. 修改Redis Template的序列化器为GenericJackson2JsonRedisSerializer;

方案二:

  1. 使用StringRedisTemplate;
  2. 写入Redis时,手动把对象序列化为 JSON;
  3. 读取Redis时,手动把读取到的JSON反序列化为对象;

标签:String,Redis,key,类型,序列化,name
From: https://www.cnblogs.com/wangzheng888/p/16898135.html

相关文章

  • Linux安装redis出现的一点问题
    gcc版本不够高安装的时候出现了:release.c:37:21:致命错误:release.h:没有那个文件或目录#include"release.h"然后发现是安装redis6.0需要gcc的版本为5.0以上,......
  • Redis入门
    一、Redis简介安装1、Redis简介REmoteDIctionaryServer(Redis)是一个由SalvatoreSanfilippo写的key-value存储系统,是跨平台的非关系型数据库。Redis是一个开......
  • Redis安装说明
    Redis安装说明大多数企业都是基于Linux服务器来部署项目,而且Redis官方也没有提供Windows版本的安装包。因此课程中我们会基于Linux系统来安装Redis.此处选择的Linux版本......
  • redis
    redis基础1.初识redisRedis是一种键值型的NoSql数据库,这里有两个关键字:键值型NoSql其中键值型,是指Redis中存储的数据都是以key、value对的形式存储,而value的形......
  • redis 数据类型
    目录redis数据类型字符串string添加一个key获取一个key的内容删除一个key批量设置多个key,value批量根据key获取多个value追加数据数值递增数值递减获取字符串key的长度判......
  • 2022-01-27 redis集群技术调研
    目录​​摘要:​​​​redis集群方案选型:​​​​redis集群前端代理proxy技术选型:​​​​redis集群的扩容/缩容:​​​​rediscluster集群的节点高可用​​​​redis节......
  • Redis学习(一)之redis中的key
    根据redis英文文档学习一下redis,从最基础的开始。 首先,我们看第一个红框内,key太大不好,否则从内存和key比较这俩方面,花费会巨大。所以,当有个一很大的key时,可以把key进行s......
  • SpringBoot 08: SpringBoot综合使用 MyBatis, Dubbo, Redis
    业务背景Student表CREATETABLE`student`(`id`int(11)NOTNULLAUTO_INCREMENT,`name`varchar(255)COLLATEutf8_binDEFAULTNULL,`phone`varchar(11)......
  • Ubuntu20 配置mysql8,redis
    mysql8安装ubuntu20库中默认的就是8.0版本sudoaptinstallmysql-server安装完成后进入mysql,起始root没有密码mysql-uroot设置root的密码usemysql;ALTERUSER......
  • redis类型操作与管道
    redis字符串操作set(name,value,ex=None,px=None,nx=False,xx=False)importredis'''ex,过期时间(秒)px,过期时间(毫秒)nx,如果设置为True,则只有name不存在时,当前se......