向redis中添加哈希值

今天遇到一个很奇怪的问题,向redis中添加哈希结构的值,不知道为什么每个key都只会加最后一条 并不是所有的值。
这是我的Java代码:

img


这是我的redis方法:

img


这是我的数据:

img

  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/7562343
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:我将redis中的key设置为永久有效为什么还是被删除了
  • 除此之外, 这篇博客: Java三种方式实现redis分布式锁中的 为redis的key设置过期时间,程序异常导致的死锁,在到达过期时间之后锁自动释放。也就说厕所门是电子锁,锁定的最长时间是有限制的,超过时长锁就会自动打开释放"坑位"资源。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • image-20220428112311092

  • 您还可以看一下 钟林森老师的Java实战之Redis入门到精通课程中的 基于Key过期失效实现 'N分钟内请勿重复提交' 功能小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    对于问题:如何向redis中添加哈希值,并保证每个key都能正确添加对应的值,而不是仅添加最后一条值?

    一种解决方案是使用分布式锁来保证并发操作时数据的正确性。

    以下是Java代码实现:

    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import redis.clients.jedis.exceptions.JedisException;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    
    public class RedisHashAddDemo {
        private final JedisPool jedisPool;
    
        public RedisHashAddDemo(JedisPool jedisPool) {
            this.jedisPool = jedisPool;
        }
    
        public void addHashValue(String hashKey, Map<String, String> values) {
            Jedis jedis = null;
            Lock lock = null;
            try {
                jedis = jedisPool.getResource();
                //获取分布式锁
                lock = RedisLockUtil.acquireLock(jedis, hashKey, 30, TimeUnit.SECONDS);
                //添加哈希值
                jedis.hmset(hashKey, values);
            } catch (JedisException e) {
                e.printStackTrace();
            } finally {
                if (lock != null) {
                    //释放锁
                    RedisLockUtil.releaseLock(lock, jedis, hashKey);
                }
                if (jedis != null) {
                    jedis.close();
                }
            }
        }
    
        public static void main(String[] args) {
            JedisPool jedisPool = new JedisPool("localhost", 6379);
            RedisHashAddDemo redisHashAddDemo = new RedisHashAddDemo(jedisPool);
            Map<String, String> values = new HashMap<>();
            values.put("key1", "value1");
            values.put("key2", "value2");
            values.put("key3", "value3");
            redisHashAddDemo.addHashValue("hashKey", values);
        }
    }
    

    其中需要用到分布式锁的实现类RedisLockUtil,以下是实现代码:

    import redis.clients.jedis.Jedis;
    
    import java.util.Collections;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    
    public class RedisLockUtil implements Lock {
        private Jedis jedis;
        private String lockKey;
        private String lockValue;
    
        public RedisLockUtil(Jedis jedis, String lockKey) {
            this.jedis = jedis;
            this.lockKey = lockKey;
        }
    
        @Override
        public void lock() {
            while (!tryLock()) {
                try {
                    //等待锁释放
                    TimeUnit.MILLISECONDS.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    
        @Override
        public void lockInterruptibly() throws InterruptedException {
            throw new UnsupportedOperationException("不支持中断加锁操作");
        }
    
        @Override
        public boolean tryLock() {
            lockValue = System.currentTimeMillis() + Thread.currentThread().getName();
            String result = jedis.set(lockKey, lockValue, "NX", "PX", 30000);
            return "OK".equals(result);
        }
    
        @Override
        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
            long timeout = unit.toMillis(time);
            while (timeout > 0) {
                if (tryLock()) {
                    return true;
                }
                timeout -= 100;
                //休眠100ms
                TimeUnit.MILLISECONDS.sleep(100);
            }
            return false;
        }
    
        @Override
        public void unlock() {
            String lockValue = jedis.get(lockKey);
            if (lockValue != null && lockValue.equals(this.lockValue)) {
                jedis.del(lockKey);
            }
        }
    
        @Override
        public Condition newCondition() {
            throw new UnsupportedOperationException("不支持条件变量操作");
        }
    
        public static Lock acquireLock(Jedis jedis, String lockKey, long timeout, TimeUnit timeUnit) {
            RedisLockUtil redisLock = new RedisLockUtil(jedis, lockKey);
            try {
                if (redisLock.tryLock(timeout, timeUnit)) {
                    return redisLock;
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            return null;
        }
    
        public static void releaseLock(Lock lock, Jedis jedis, String lockKey) {
            if (lock != null) {
                lock.unlock();
            }
            jedis.close();
        }
    }
    

    在添加哈希值时,获取分布式锁,然后执行哈希值的添加操作。如果有其他线程在此期间获取到了锁,则会等待锁的释放。在操作结束后,需要释放锁。这样即可保证每个key正确添加对应的值,而不是仅添加最后一条值。

打印出 jdbcList 看看内容,或者在 forEach 里面打印出几个关键的值。

key被覆盖了,所以永远是最后一条数据