redis zremove删除不掉【bug】

前言

2024-4-12 20:35:21

以下内容源自《【bug】》
仅供学习交流使用

版权

禁止其他平台发布时删除以下此话
本文首次发布于CSDN平台
作者是CSDN@日星月云
博客主页是https://blog.csdn.net/qq_51625007
禁止其他平台发布时删除以上此话

redis zremove删除不掉

测试一

  1. 调用添加数据:testAddData20
  2. 调用修改数据:testUpdateData
  3. 调用删除方法:testRemoveData20

结果:调用删除新的数据,旧的数据就会重新出现

1.
{date=[2024-04-13], rate1=[20], rate2=[20], id=[20]}
2.
true
{date=[2024-04-13], rate1=[22], rate2=[22], id=[20]}
3.
1
{date=[2024-04-13], rate1=[20], rate2=[20], id=[20]}

测试二:

  1. 调用添加数据:testAddData
  2. 调用删除方法:testRemoveData20

结果:删除成功,只有数据完全一样才行

1.
{date=[2024-04-13, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12], rate1=[20, 9, 8, 7, 6, 5, 4, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 3, 2, 1], rate2=[20, 9, 8, 7, 6, 5, 4, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 3, 2, 1], id=[20, 9, 8, 7, 6, 5, 4, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 3, 2, 1]}
2.
1
{date=[2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12, 2024-04-12], rate1=[9, 8, 7, 6, 5, 4, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 3, 2, 1], rate2=[9, 8, 7, 6, 5, 4, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 3, 2, 1], id=[9, 8, 7, 6, 5, 4, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 3, 2, 1]}

错误产生

为什么可以修改,但是不能删除

在上面的代码中,虽然使用了自定义序列化器和比较方法来实现根据特定条件或属性删除数据,但是在实际操作中,Redis有序集合的remove方法确实只能删除完全相同的数据。

这是因为在Redis的有序集合中,元素是通过score进行排序的,而remove方法是根据元素的值来删除的。如果元素的值完全相同,那么remove方法可以成功删除。但是如果元素的值中的某些属性或条件不同,即使其他属性相同,remove方法也无法删除这样的数据。

因此,如果希望根据特定属性或条件删除数据,可以考虑使用其他数据结构或方法来实现,比如使用Redis的哈希表来存储数据,然后通过特定的属性作为键来删除数据。或者在应用层进行数据的筛选和删除操作,然后再写回Redis中。

不能根据equals方法判断的吗

对于Java中的对象,可以通过重写equals方法来自定义判断两个对象是否相等。但是在Redis中,数据是以字符串或字节数组的形式存储的,并没有对对象的equals方法进行支持。

在Redis中,有序集合的remove方法是根据元素的值来删除的,而不是根据对象的equals方法。只有完全相同的值才可以被成功删除,否则无法删除。

如果希望根据对象的equals方法来判断是否删除数据,通常需要在应用层进行操作,先获取到数据再进行比较,然后再删除数据。或者可以使用其他数据结构或方法来实现根据对象的equals方法来删除数据。Redis本身并不提供根据对象的equals方法进行删除的功能。

应该是与序列化和反序列化有关。

相关资源

EldData

package com.jsss.echarts.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.sql.Date;
import java.util.Objects;


@Data
@NoArgsConstructor
@AllArgsConstructor

public class EldData {
    String id;
    Integer rate1;
    Integer rate2;
    Date date;

 public EldData(String id, Date date) {
        this.id = id;
        this.date = date;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        EldData eldData = (EldData) o;
        return Objects.equals(id, eldData.id) && Objects.equals(date, eldData.date);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, date);
    }
    
    @Override
    public String toString() {
        return "EldData{" +
                "rate1=" + rate1 +
                ", rate2=" + rate2 +
                ", date=" + date +
                '}';
    }
}

EchartsTest

package com.jsss.echarts.service;

import com.jsss.echarts.entity.EldData;
import com.jsss.utils.Constant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

@Service
public class DataService implements Constant {


    @Autowired
    RedisTemplate redisTemplate;


    //返回数据链表
    public HashMap<String,ArrayList> searchMap(Integer userId){
        HashMap<String,ArrayList> map=new HashMap<>();
        List<EldData> dataList = search(userId);

        List<String> fieldNames = new ArrayList<>();
        Class<?> dataClass = EldData.class;

        // 获取 OldData 类的所有属性名
        Field[] fields = dataClass.getDeclaredFields();
        for (Field field : fields) {
            fieldNames.add(field.getName());
            map.put(field.getName(),new ArrayList<>());
        }


        for (EldData data : dataList) {
            for (String fieldName : fieldNames) {
                ArrayList<Object> rowData =map.get(fieldName);
                try {
                    Field field = dataClass.getDeclaredField(fieldName);
                    field.setAccessible(true);
                    rowData.add(field.get(data));
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    e.printStackTrace();
                }
                map.put(fieldName,rowData);
            }

        }
        return map;
    }

    //搜索数据
    public List<EldData> search(Integer userId) {
        String key= ELD_DATA +userId;
        Set set = redisTemplate.opsForZSet().reverseRange(key, 0, 19);// 获取分数最高的20个数据

        return set !=null?new ArrayList<>(set):new ArrayList<>();

    }

    // 将数据存储到有序集合中,分数为日期的时间戳
    public boolean addData(Integer userId, EldData data) {
        String key= ELD_DATA +userId;
        return redisTemplate.opsForZSet().add(key, data,data.getDate().getTime());
    }

    // 更新数据,如果数据已存在则会覆盖
    public boolean updateData(Integer userId, EldData newData) {
        String key= ELD_DATA +userId;
        return redisTemplate.opsForZSet().add(key, newData, newData.getDate().getTime());
    }

    // 删除指定的数据
    public long removeData(Integer userId, EldData data) {
        String key= ELD_DATA +userId;
        return redisTemplate.opsForZSet().remove(key, data);
    }

    @Test
    public void test2() {
        System.out.println("1.");
        testAddData20();
        System.out.println("2.");
        testUpdateData();
        System.out.println("3.");
        testRemoveData();

    }

}

DataService

package com.jsss.echarts.service;

import com.jsss.echarts.entity.EldData;
import com.jsss.utils.Constant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

@Service
public class DataService implements Constant {


    @Autowired
    RedisTemplate redisTemplate;


    //返回数据链表
    public HashMap<String,ArrayList> searchMap(Integer userId){
        HashMap<String,ArrayList> map=new HashMap<>();
        List<EldData> dataList = search(userId);

        List<String> fieldNames = new ArrayList<>();
        Class<?> dataClass = EldData.class;

        // 获取 OldData 类的所有属性名
        Field[] fields = dataClass.getDeclaredFields();
        for (Field field : fields) {
            fieldNames.add(field.getName());
            map.put(field.getName(),new ArrayList<>());
        }


        for (EldData data : dataList) {
            for (String fieldName : fieldNames) {
                ArrayList<Object> rowData =map.get(fieldName);
                try {
                    Field field = dataClass.getDeclaredField(fieldName);
                    field.setAccessible(true);
                    rowData.add(field.get(data));
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    e.printStackTrace();
                }
                map.put(fieldName,rowData);
            }

        }
        return map;
    }

    //搜索数据
    public List<EldData> search(Integer userId) {
        String key= ELD_DATA +userId;
        Set set = redisTemplate.opsForZSet().reverseRange(key, 0, 19);// 获取分数最高的20个数据

        return set !=null?new ArrayList<>(set):new ArrayList<>();

    }

    // 将数据存储到有序集合中,分数为日期的时间戳
    public boolean addData(Integer userId, EldData data) {
        String key= ELD_DATA +userId;
        return redisTemplate.opsForZSet().add(key, data,data.getDate().getTime());
    }

    // 更新数据,如果数据已存在则会覆盖
    public boolean updateData(Integer userId, EldData newData) {
        String key= ELD_DATA +userId;
        return redisTemplate.opsForZSet().add(key, newData, newData.getDate().getTime());
    }

    // 删除指定的数据
    public long removeData(Integer userId, EldData data) {
        String key= ELD_DATA +userId;
        return redisTemplate.opsForZSet().remove(key, data);
    }


}

解决

不知道怎么解决

修改更新业务
先删除旧的,再添加新的
保证只有一个equals对象

   // 将数据存储到有序集合中,分数为日期的时间戳
    public boolean addData(Integer userId, EldData data) {
        String key= ELD_DATA +userId;
        return redisTemplate.opsForZSet().add(key, data,data.getDate().getTime());
    }

    // 更新数据,先删除数据,后增加新数据
    public boolean updateData(Integer userId,EldData oldData,EldData newData) {
        long res=removeData(userId,oldData);
        if (res==0){
            //没有旧数据,就修改失败
            return false;
        }
        return addData(userId, newData);
    }

    // 删除指定的数据
    public long removeData(Integer userId, EldData data) {
        String key= ELD_DATA +userId;
        return redisTemplate.opsForZSet().remove(key, data);
    }

对应的测试方法

    @Test
    public void testUpdateData() {
        EldData oldData=new EldData(String.valueOf(20),20,20,date);
        EldData newData=new EldData(String.valueOf(20),22,22,date);
        System.out.println(dataService.updateData(userId, oldData,newData));
        testSearchMap();
    }

测试test1,结果:

1.
{date=[2024-04-13], rate1=[20], rate2=[20], id=[20]}
2.
true
{date=[2024-04-13], rate1=[22], rate2=[22], id=[20]}
3.
1
{date=[], rate1=[], rate2=[], id=[]}

最后

2024-4-12 21:31:23

我们都有光明的未来

祝大家考研上岸
祝大家工作顺利
祝大家得偿所愿
祝大家如愿以偿
点赞收藏关注哦

相关推荐

  1. redis zremove删除bug

    2024-04-21 00:10:01       12 阅读
  2. redis zremove删除bug

    2024-04-21 00:10:01       23 阅读
  3. conda env list,列出来的环境怎么删除

    2024-04-21 00:10:01       9 阅读
  4. bug是测完的,根本测

    2024-04-21 00:10:01       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-21 00:10:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-21 00:10:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-21 00:10:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-21 00:10:01       20 阅读

热门阅读

  1. draw.io使用心得

    2024-04-21 00:10:01       15 阅读
  2. 发挥创意,绘制无限可能:draw.io 使用心得

    2024-04-21 00:10:01       15 阅读
  3. Excel使用 CONCATENATE 函数或“&”符号拼接多列数据

    2024-04-21 00:10:01       30 阅读
  4. js高级 笔记01

    2024-04-21 00:10:01       15 阅读
  5. Golang最快的Web框架

    2024-04-21 00:10:01       16 阅读
  6. 【算法基础】第四章:数学知识

    2024-04-21 00:10:01       14 阅读
  7. 【总结】网络安全工作岗位分类

    2024-04-21 00:10:01       16 阅读
  8. 设计模式|适配器模式(Adapter Pattern)

    2024-04-21 00:10:01       17 阅读
  9. 探索Python爬虫利器:Scrapy框架解析与实战

    2024-04-21 00:10:01       14 阅读
  10. 最新消息:台积电因地震损失30亿新台币

    2024-04-21 00:10:01       10 阅读