✨✨个人主页:沫洺的主页
📚📚系列专栏: 📖 JavaWeb专栏📖 JavaSE专栏 📖 Java基础专栏📖vue3专栏
📖MyBatis专栏📖Spring专栏📖SpringMVC专栏📖SpringBoot专栏
📖Docker专栏📖Reids专栏📖MQ专栏📖SpringCloud专栏
💖💖如果文章对你有所帮助请留下三连✨✨
💦*Operations底层原理
以ValueOperations为例底层还是调用的opsForValue
相当于对redisTemplate.opsForValue()进行封装
💤ValueOperations
@SpringBootTest class AppTests_Operations { @Resource(name = "redisTemplate") private ValueOperations<String,User> valueOperations; @Test public void test1(){ valueOperations.set("user2", User.builder().name("李四").age(24).build()); valueOperations.set("user3", User.builder().name("王五").age(25).build()); System.out.println(valueOperations.get("user2")); //获取后删除 System.out.println(valueOperations.getAndDelete("user3")); //setnx锁,存在与否 System.out.println(valueOperations.setIfAbsent("user2", User.builder().name("老李").age(4).build())); System.out.println(valueOperations.setIfAbsent("user4", User.builder().name("老李").age(4).build())); //设置获取并声明周期 System.out.println(valueOperations.getAndExpire("user4", 30, TimeUnit.SECONDS)); //批量设置 Map<String,User> map = new HashMap<>(); map.put("u1",User.builder().name("张一").age(11).build()); map.put("u2",User.builder().name("张二").age(22).build()); valueOperations.multiSet(map); ArrayList<String> list = new ArrayList<>(); list.add("u1"); list.add("u2"); System.out.println(valueOperations.multiGet(list)); } }
💤ListOperations
@SpringBootTest class AppTests_Operations { @Resource(name = "redisTemplate") private ListOperations<String,User> listOperations; @Test public void test2(){ listOperations.leftPush("user1", User.builder().name("张三").age(23).build()); listOperations.leftPush("user1", User.builder().name("李四").age(24).build()); //批量左推 //listOperations.leftPushAll() //左弹 System.out.println(listOperations.leftPop("user1")); //长度 System.out.println(listOperations.size("user1")); } }
💤SetOperations
@SpringBootTest class AppTests_Operations { @Resource(name = "redisTemplate") private SetOperations<String,String> setOperations; @Test public void test3(){ setOperations.add("class1","张三", "李四", "王五"); setOperations.add("class2","张三丰", "李四", "王五"); //交集 System.out.println(setOperations.intersect("class1", "class2")); //并集 System.out.println(setOperations.union("class1", "class2")); //差集 System.out.println(setOperations.difference("class1", "class2")); //是否存在 System.out.println(setOperations.isMember("class1","张三")); } }
💤ZSetOperations
@SpringBootTest class AppTests_Operations { @Resource(name = "redisTemplate") private ZSetOperations<String,User> zSetOperations; @Test public void test4(){ zSetOperations.add("class1", User.builder().name("张三").age(23).build(), 23); zSetOperations.add("class1", User.builder().name("李四").age(24).build(), 24); zSetOperations.add("class1", User.builder().name("王五").age(25).build(), 25); //长度 System.out.println(zSetOperations.size("class1")); //范围数量 System.out.println(zSetOperations.count("class1", 0, 100)); //最值 //System.out.println(zSetOperations.popMax("class1")); //System.out.println(zSetOperations.popMin("class1")); //范围内的值,根据分数升序 System.out.println(zSetOperations.rangeByScore("class1", 0, 100)); //排名 System.out.println(zSetOperations.rank("class1", User.builder().name("张三").age(23).build())); //倒叙 System.out.println(zSetOperations.reverseRangeByScore("class1", 10, 30)); } }
💤HashOperations
@SpringBootTest class AppTests_Operations { @Resource(name = "redisTemplate") private HashOperations<String,String,User> hashOperations; @Test public void test5(){ hashOperations.put("class.211", "user1", User.builder().name("李四").age(24).build()); System.out.println(hashOperations.get("class.211", "user1")); //所有键值 System.out.println(hashOperations.entries("class.211")); //所有值 System.out.println(hashOperations.values("class.211")); //所有key System.out.println(hashOperations.keys("class.211")); //是否存在某域(小key) System.out.println(hashOperations.hasKey("class.211","user1")); System.out.println(hashOperations.hasKey("class.211","user2")); //批量 Map<String,User> map = new HashMap<>(); map.put("u1",User.builder().name("张一").age(11).build()); map.put("u2",User.builder().name("张二").age(22).build()); hashOperations.putAll("class.211", map); } }
💥Redis慢日志
SLOWLOG 是用来读取和重置 Redis 慢查询日志的命令,Redis 2.2.12 版本开始支持
💨Redis 慢查询日志概述
客户端从发送命令到获取返回结果经过了以下几个步骤:
1. 客户端发送命令
2. 该命令进入 Redis 队列排队等待执行
3. Redis 开始执行命令 --- Redis 命令执行完成
4. 命令执行结果返回给客户端
Redis 慢查询日志统计的时间,只包含第三步的 Redis 命令从开始执行到执行完成的时间。
💨慢查询日志的两个配置项
slowlog-log-slower-than
Redis 慢查询日志的时间阈值,单位微妙。
1) 值为正数,执行时间大于该值设置的微秒时才记录到慢日志中。默认 10000 微秒。
2) 值为负数,禁用慢查询日志。
3) 值为 0,所有命令都记录到慢日志中
slowlog-max-len
慢查询日志长度,最小值为零。默认 128
当记录新命令并且当前慢日志已达到最大长度时,最旧的一条记录将被删除。
可以通过编辑 redis.conf 或者使用 CONFIG GET/SET 命令来进行配置
方法一: 使用 config get/set 命令配置
方法二: 编辑 redis.conf
💨读取慢日志记录
慢查询日志是记录在内存中的,记录速度非常快。
可以使用 SLOWLOG GET N 命令来读取慢日志,查询最近的 N 条记录。
该命令默认请求条数为 10 ,即 SLOWLOG GET 等价于 SLOWLOG GET 10
参数为 -1 时会获取整个慢日志信息。
模拟读取慢日志
由于redis读取速度比较快,这里将慢查询日志的时间阈值设为0微妙
测试类向redis数据库中设置100条数据
@SpringBootTest class AppTests_SlowLog { @Resource(name = "redisTemplate") private ValueOperations<String, User> valueOperations; @Test void test1() { for (int i =1 ;i<101;i++){ User user = User.builder().name(i+"号张").age(18).build(); valueOperations.set("user."+i,user); } } }
使用命令slowlog get 1 查1条记录
127.0.0.1:6379> slowlog get 2 1) 1) (integer) 13 2) (integer) 1629523068 3) (integer) 6 4) 1) "get" 2) "a" 5) "127.0.0.1:43942" 6) "lnrcoder"
日志输出格式
1)每条日志唯一标识符
2)命令执行时的时间戳
3)命令执行消耗的时间,单位微秒
4)执行的命令数组
5)客户端地址和端口 (仅 4.0 以上版本支持)
6)客户端名称 (仅 4.0 以上版本支持,默认名称为空,需要通过 client setname 命令进行设置)
💨查询慢日志记录长度
使用 SLOWLOG LEN 可以获取慢日志记录的长度。
127.0.0.1:6379> slowlog len (integer) 2
💨重置慢日志
使用 SLOWLOG RESET 命令用来重置慢日志。使用该命令进行日志重置后,信息将永远丢失。
127.0.0.1:6379> slowlog len (integer) 10 127.0.0.1:6379> slowlog reset OK 127.0.0.1:6379> slowlog len (integer) 0