Redis优化笔记

Redis优化

一:Key:

1.1.Key的规范:

image-20240519214240615
测试如下:
image-20240519214354630

1.2.拒绝BigKey:

image-20240519214511678
我们可以用:
MEMORY USAGE name
命令来看它的大小。

在这里插入图片描述

image-20240519214823088

注意,这里的第二种之所以不使用Keys *,因为在实际生产时,会阻塞线程,而scan就不会。使用举例:
import com.heima.jedis.util.JedisConnectionFactory;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanResult;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JedisTest {
    private Jedis jedis;

    @BeforeEach
    void setUp() {
        // 1.建立连接
        // jedis = new Jedis("192.168.150.101", 6379);
        jedis = JedisConnectionFactory.getJedis();
        // 2.设置密码
        jedis.auth("123321");
        // 3.选择库
        jedis.select(0);
    }

    final static int STR_MAX_LEN = 10 * 1024;
    final static int HASH_MAX_LEN = 500;

    @Test
    void testScan() {
        int maxLen = 0;
        long len = 0;

        String cursor = "0";
        do {
            // 扫描并获取一部分key
            ScanResult<String> result = jedis.scan(cursor);
            // 记录cursor
            cursor = result.getCursor();
            List<String> list = result.getResult();
            if (list == null || list.isEmpty()) {
                break;
            }
            // 遍历
            for (String key : list) {
                // 判断key的类型
                String type = jedis.type(key);
                switch (type) {
                    case "string":
                        len = jedis.strlen(key);
                        maxLen = STR_MAX_LEN;
                        break;
                    case "hash":
                        len = jedis.hlen(key);
                        maxLen = HASH_MAX_LEN;
                        break;
                    case "list":
                        len = jedis.llen(key);
                        maxLen = HASH_MAX_LEN;
                        break;
                    case "set":
                        len = jedis.scard(key);
                        maxLen = HASH_MAX_LEN;
                        break;
                    case "zset":
                        len = jedis.zcard(key);
                        maxLen = HASH_MAX_LEN;
                        break;
                    default:
                        break;
                }
                if (len >= maxLen) {
                    System.out.printf("Found big key : %s, type: %s, length or size: %d %n", key, type, len);
                }
            }
        } while (!cursor.equals("0"));
    }
    
    @AfterEach
    void tearDown() {
        if (jedis != null) {
            jedis.close();
        }
    }

}
建议放在从节点进行。

在这里插入图片描述

1.3.合适的结构:

在这里插入图片描述

用Hash存储:

在这里插入图片描述

用string:

在这里插入图片描述

用多级Hash:

在这里插入图片描述

二:批处理优化:

2.1.MSET与Pipeline:

导入大量数据,一次导入与多次导入谁时间更优秀呢:

先来看看多次导入:

在这里插入图片描述

通过测试,导入时间主要是花在了网络传输上面了。因此,这明显不如第二种:

在这里插入图片描述

下面我们来看看基于mset的批处理:

在这里插入图片描述

但是,有很多的命令具有局限性,其他的数据结构未必有批处理,就算是集合,它的sadd也只是针对同一个key而已。所以我们使用Pipeline:

当然,在spring-redis中,也有批处理,举例如下:
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.data.redis.core.RedisCallback;  
import org.springframework.data.redis.core.RedisTemplate;  
import org.springframework.data.redis.connection.RedisConnection;  
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;  
import io.lettuce.core.api.StatefulRedisConnection;  
import io.lettuce.core.api.sync.RedisCommands;  
  
@Service  
public class RedisPipelinedService {  
  
    @Autowired  
    private RedisTemplate<String, String> redisTemplate;  
  
    public void executePipelinedCommands() {  
        redisTemplate.executePipelined((RedisCallback<Object>) connection -> {  
            RedisCommands<String, String> commands = connection.sync();  
              
            // 添加多个命令到 pipeline  
            commands.set("key1", "value1");  
            commands.set("key2", "value2");  
            // ... 可以添加更多命令  
  
            // 注意:不需要在这里调用任何返回结果的方法,因为 pipelined 命令是异步的  
            return null; // RedisCallback 需要返回 Object,但在这里我们不需要它  
        });  
  
        // 注意:上面的 executePipelined 方法是异步的,但会返回一个 List,其中包含每个命令的响应  
        // 你可以在这里处理这些响应,但在这个例子中我们忽略了它们  
    }  
  
    // 如果你需要更底层的访问(例如,直接使用 Lettuce 的 StatefulRedisConnection),  
    // 你可以从 LettuceConnectionFactory 获取它,但通常不建议这样做,除非你有特殊需求。  
}
小细节:mset快于Pipeline。

2.2.集群下的批处理:

在这里插入图片描述

在这里插入图片描述

串行:

在这里插入图片描述

并行:
我们还可以使用Spring的方法来实现并行:

在这里插入图片描述

三:服务端优化:

3.1.持久化配置:

在这里插入图片描述

关于第五点:为什么要有这样一个配置:

在这里插入图片描述

这是AOF的刷盘机制,我们可以看到,当刷盘时间大于2s,会导致主节点阻塞,而如果我们在进行刷盘时,磁盘也在进行大量的IO,比如AOF的重写,或者RDB的fork,就会很容易导致主线程等待时间过长。当然,如果设置为yes,可能会丢失一段数据。

3.2.慢查询:

在这里插入图片描述

在这里插入图片描述

当我们执行了一个keys *后,比如我们用慢查询日志来查看一下:

在这里插入图片描述

当然,在redis客户端,可以直接看到慢查询日志:

在这里插入图片描述

这是一些其他的命令;

在这里插入图片描述

3.3.命令与安全配置:

在这里插入图片描述

举例:

在这里插入图片描述

设置为“”表示不允许使用,而第一种表示要用它来替代改命令,其他人就不可能破解。

3.4.内存配置:

在这里插入图片描述

定期重启可以清除数据内存,而进程问题影响也不是很大,所以我们主要是缓冲区问题。

在这里插入图片描述

在这里插入图片描述

四:集群与主从:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Java秒杀系统方案优化高性能高并发学习实战源代码以及笔记..zip 章节笔记 第1章-课程介绍及项目框架搭建 知识点 使用spring boot 搭建项目基础框架 使用Thymeleaf做页面展示,封装Result统一结果 集成 mybatis + druid 做数据操作 继承redis, 使用Jedis操作redis数据, 封装了统一的缓存key. 第2章-实现用户登录以及分布式session功能 学习了自己通过 cookie 实现分布式session, 不使用spring boot默认提供的 知识点 数据库设计 明文密码两次md5处理 JSR303参数校验 + 全局异常处理器 分布式session, 通过cookie完成分布式session功能. 将cookie存放到redis中. 第3章-秒杀功能开发及管理后台 学习到了基础的商品下单流程, 查库存,查是否重复下单,减库存,创建订单等过程 知识点 数据库设计(业务第一原则, 无需太注意三大范式) 完成商品列表页 完成商品详情页 完成订单详情页 第4章-秒杀压测-Jmeter压力测试 学习使用jmeter做压力测试, 学习jmeter变量定义, redis压力测试工具 知识点 jemter入门 自定义变量模拟多用户(线程组 -> 添加 -> 配置元件 -> CVS数据文件设置) jmeter在命令行下的使用. 下载tgz,解压缩并替换windows视窗下面配置的CVS信息路径 执行脚本 ./bin/jmeter.sh -n -t xxx.jmx -l result.jtl 完成后可以将result下载下来导入到 聚合报告 中查看 spring boot 打war包. 添加 plugins 插件 <!--打war包插件--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> 添加tomcat依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> 编写启动类 public class ServletApplication extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(ServletApplication.class); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xiao Ling.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值