有域名自己做網(wǎng)站嗎網(wǎng)絡(luò)推廣長沙網(wǎng)絡(luò)推廣
redis zremove刪除不掉【bug】
- 前言
- 版權(quán)
- redis zremove刪除不掉
- 錯誤產(chǎn)生
- 相關(guān)資源
- EldData
- EchartsTest
- DataService
- 解決
- 最后
前言
2024-4-12 20:35:21
以下內(nèi)容源自《【bug】》
僅供學(xué)習(xí)交流使用
版權(quán)
禁止其他平臺發(fā)布時刪除以下此話
本文首次發(fā)布于CSDN平臺
作者是CSDN@日星月云
博客主頁是https://blog.csdn.net/qq_51625007
禁止其他平臺發(fā)布時刪除以上此話
redis zremove刪除不掉
測試一:
- 調(diào)用添加數(shù)據(jù):testAddData20
- 調(diào)用修改數(shù)據(jù):testUpdateData
- 調(diào)用刪除方法:testRemoveData20
結(jié)果:調(diào)用刪除新的數(shù)據(jù),舊的數(shù)據(jù)就會重新出現(xiàn)
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]}
測試二:
- 調(diào)用添加數(shù)據(jù):testAddData
- 調(diào)用刪除方法:testRemoveData20
結(jié)果:刪除成功,只有數(shù)據(jù)完全一樣才行
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]}
錯誤產(chǎn)生
為什么可以修改,但是不能刪除
在上面的代碼中,雖然使用了自定義序列化器和比較方法來實現(xiàn)根據(jù)特定條件或?qū)傩詣h除數(shù)據(jù),但是在實際操作中,Redis有序集合的remove方法確實只能刪除完全相同的數(shù)據(jù)。
這是因為在Redis的有序集合中,元素是通過score進(jìn)行排序的,而remove方法是根據(jù)元素的值來刪除的。如果元素的值完全相同,那么remove方法可以成功刪除。但是如果元素的值中的某些屬性或條件不同,即使其他屬性相同,remove方法也無法刪除這樣的數(shù)據(jù)。
因此,如果希望根據(jù)特定屬性或條件刪除數(shù)據(jù),可以考慮使用其他數(shù)據(jù)結(jié)構(gòu)或方法來實現(xiàn),比如使用Redis的哈希表來存儲數(shù)據(jù),然后通過特定的屬性作為鍵來刪除數(shù)據(jù)?;蛘咴趹?yīng)用層進(jìn)行數(shù)據(jù)的篩選和刪除操作,然后再寫回Redis中。
不能根據(jù)equals方法判斷的嗎
對于Java中的對象,可以通過重寫equals方法來自定義判斷兩個對象是否相等。但是在Redis中,數(shù)據(jù)是以字符串或字節(jié)數(shù)組的形式存儲的,并沒有對對象的equals方法進(jìn)行支持。
在Redis中,有序集合的remove方法是根據(jù)元素的值來刪除的,而不是根據(jù)對象的equals方法。只有完全相同的值才可以被成功刪除,否則無法刪除。
如果希望根據(jù)對象的equals方法來判斷是否刪除數(shù)據(jù),通常需要在應(yīng)用層進(jìn)行操作,先獲取到數(shù)據(jù)再進(jìn)行比較,然后再刪除數(shù)據(jù)?;蛘呖梢允褂闷渌麛?shù)據(jù)結(jié)構(gòu)或方法來實現(xiàn)根據(jù)對象的equals方法來刪除數(shù)據(jù)。Redis本身并不提供根據(jù)對象的equals方法進(jìn)行刪除的功能。
應(yīng)該是與序列化和反序列化有關(guān)。
相關(guān)資源
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
@AllArgsConstructorpublic class EldData {String id;Integer rate1;Integer rate2;Date date;public EldData(String id, Date date) {this.id = id;this.date = date;}@Overridepublic 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);}@Overridepublic int hashCode() {return Objects.hash(id, date);}@Overridepublic 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 {@AutowiredRedisTemplate redisTemplate;//返回數(shù)據(jù)鏈表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;}//搜索數(shù)據(jù)public List<EldData> search(Integer userId) {String key= ELD_DATA +userId;Set set = redisTemplate.opsForZSet().reverseRange(key, 0, 19);// 獲取分?jǐn)?shù)最高的20個數(shù)據(jù)return set !=null?new ArrayList<>(set):new ArrayList<>();}// 將數(shù)據(jù)存儲到有序集合中,分?jǐn)?shù)為日期的時間戳public boolean addData(Integer userId, EldData data) {String key= ELD_DATA +userId;return redisTemplate.opsForZSet().add(key, data,data.getDate().getTime());}// 更新數(shù)據(jù),如果數(shù)據(jù)已存在則會覆蓋public boolean updateData(Integer userId, EldData newData) {String key= ELD_DATA +userId;return redisTemplate.opsForZSet().add(key, newData, newData.getDate().getTime());}// 刪除指定的數(shù)據(jù)public long removeData(Integer userId, EldData data) {String key= ELD_DATA +userId;return redisTemplate.opsForZSet().remove(key, data);}@Testpublic 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 {@AutowiredRedisTemplate redisTemplate;//返回數(shù)據(jù)鏈表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;}//搜索數(shù)據(jù)public List<EldData> search(Integer userId) {String key= ELD_DATA +userId;Set set = redisTemplate.opsForZSet().reverseRange(key, 0, 19);// 獲取分?jǐn)?shù)最高的20個數(shù)據(jù)return set !=null?new ArrayList<>(set):new ArrayList<>();}// 將數(shù)據(jù)存儲到有序集合中,分?jǐn)?shù)為日期的時間戳public boolean addData(Integer userId, EldData data) {String key= ELD_DATA +userId;return redisTemplate.opsForZSet().add(key, data,data.getDate().getTime());}// 更新數(shù)據(jù),如果數(shù)據(jù)已存在則會覆蓋public boolean updateData(Integer userId, EldData newData) {String key= ELD_DATA +userId;return redisTemplate.opsForZSet().add(key, newData, newData.getDate().getTime());}// 刪除指定的數(shù)據(jù)public long removeData(Integer userId, EldData data) {String key= ELD_DATA +userId;return redisTemplate.opsForZSet().remove(key, data);}}
解決
不知道怎么解決
修改更新業(yè)務(wù)
先刪除舊的,再添加新的
保證只有一個equals對象
// 將數(shù)據(jù)存儲到有序集合中,分?jǐn)?shù)為日期的時間戳public boolean addData(Integer userId, EldData data) {String key= ELD_DATA +userId;return redisTemplate.opsForZSet().add(key, data,data.getDate().getTime());}// 更新數(shù)據(jù),先刪除數(shù)據(jù),后增加新數(shù)據(jù)public boolean updateData(Integer userId,EldData oldData,EldData newData) {long res=removeData(userId,oldData);if (res==0){//沒有舊數(shù)據(jù),就修改失敗return false;}return addData(userId, newData);}// 刪除指定的數(shù)據(jù)public long removeData(Integer userId, EldData data) {String key= ELD_DATA +userId;return redisTemplate.opsForZSet().remove(key, data);}
對應(yīng)的測試方法
@Testpublic 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,結(jié)果:
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
我們都有光明的未來
祝大家考研上岸
祝大家工作順利
祝大家得償所愿
祝大家如愿以償
點贊收藏關(guān)注哦