11redis搭建与入门

1.redis介绍

redis是一种基于内存的非关系型数据库,数据存储在内存,所以读写速度很快,但是内存大小有限,所以能存储的内容也是有限的,而且因为存储在内存,所以并不是永久化存储,比如说我将服务器重启,内存中的数据就会丢失,或者内存定期清理等都会导致数据的丢失。

redis最大的优点就是读写速度快,可能读者对于redis读写速度没有概念,下面是量化的对比:

Redis 速度优势

  • 读速度:约 100,000-200,000 次 / 秒
  • 写速度:约 80,000-150,000 次 / 秒
  • 响应延迟:微秒级(通常 100-200 微秒)

MySQL 速度参考

  • 单实例简单查询:约 10,000-30,000 次 / 秒
  • 复杂查询:几百到几千次 / 秒
  • 响应延迟:毫秒级(通常 2-10 毫秒)

可以看到redis的读写速度能岔开10倍以上

基于redis读写快、存储数据量有限、数据不能永久存储的特定,redis常用来做缓存。
比如说我现在要去查询id为1的用户的密码,原来是直接去mysql查询,但是现在我们是先去redis查询一遍,如果有,就直接返回,如果没有,就去mysql中查询,然后把查询结果存储到redis,然后再返回。redis速度很快,查询redis和向redis写入数据的时间几乎可以忽略不计。所以在项目中加入redis后性能会提高

2.redis以及图形化工具的安装

1.登录宝塔面板(或者直接在虚拟机命令行中)在/root文件夹下创建redis文件夹,其中有两个文件夹,一个conf,一个data,conf中创建一个文本文件redis.conf

2.在宝塔面板终端输入

docker run \
--restart=always \
--log-opt max-size=100m \
--log-opt max-file=2 \
-p 6379:6379 \
--name redis \
--network hm-net \
-v /root/redis/conf/redis.conf:/etc/redis/redis.conf \
-v /root/redis/data:/data \
-d redis redis-server /etc/redis/redis.conf \
--appendonly yes \
--requirepass 123456

3.安装图形化工具

Releases · lework/RedisDesktopManager-Windows

安装好后可以看到文件夹以及其中的exe文件

打开后远程连接

然后点击左下角测试连接,如果显示测试成功,就是成功了

3.redis基础教程

这里有个快速入门教程:

黑马Redis快速入门,一套搞定Redis,常见数据结构及命令,包含jedis应用与优化、springdataRedis应用与优化_哔哩哔哩_bilibili

4.在SpringBoot详细中使用redis

在SpringBoot中最常用的是SpringDataRedis来操作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>

配置文件(host和password需要修改)

spring:
  redis:
    host: 192.168.150.101
    port: 6379
    password: 123321
    lettuce:
      pool:
        max-active: 8  #最大连接
        max-idle: 8   #最大空闲连接
        min-idle: 0   #最小空闲连接
        max-wait: 100ms #连接等待时间

测试用例

@SpringBootTest
class RedisDemoApplicationTests {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Test
    void testString() {
        // 写入一条String数据
        redisTemplate.opsForValue().set("name", "虎哥");
        // 获取string数据
        Object name = redisTemplate.opsForValue().get("name");
        System.out.println("name = " + name);
    }
}

但是这个原始的RedisTemplate有问题:RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化。JDK序列化的结果不方便阅读、占用内存大

比如上面的例子存入的是name和虎哥,但实际存入的是”\xac\xed\x00\x05t\x00\x04name”和”\xac\xed\x00\x05t\x00\x06\xe8\x99\x8e\xe5\x93\xa5″我们有两种方式优化这个问题。

5.SpringBoot中优化redis

5.1自定义RedisTemplate

我们可以自定义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;
    }
}

然后使用我们自己的redisTemplate来代替原始的RedisTemplate,这样很方便,但是有一点小问题,redis存储的是key和value,如果这个value是一个对象,会出现下图这种存储多余内容的情况:

这个内容是用来反序列化时使用,但是会占用多余的内存空间。第二种方法就能解决这个问题

5.2StringRedisTemplate

为了减少内存的消耗,我们可以采用手动序列化的方式,换句话说,就是不借助默认的序列化器,而是我们自己来控制序列化的动作,同时,我们只采用String的序列化器,这样,在存储value时,我们就不需要在内存中就不用多存储数据,从而节约我们的内存空间

这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用:

@SpringBootTest
class RedisStringTests {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    void testString() {
        // 写入一条String数据
        stringRedisTemplate.opsForValue().set("verify:phone:13600527634", "124143");
        // 获取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("虎哥", 21);
        // 手动序列化
        String json = mapper.writeValueAsString(user);
        // 写入数据
        stringRedisTemplate.opsForValue().set("user:200", json);

        // 获取数据
        String jsonUser = stringRedisTemplate.opsForValue().get("user:200");
        // 手动反序列化
        User user1 = mapper.readValue(jsonUser, User.class);
        System.out.println("user1 = " + user1);
    }

}

相对于自定义RedisTemplate,这个方法更节省内存空间,但是这个方法需要每个需要存入数据的地方都手动序列化和反序列化,比较麻烦。

项目下载地址

gupengzu/high-concurrency-project at 11redis-introduction

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注