程序员王小瑞 2023-06-06 12:38 采纳率: 19.2%
浏览 95
已结题

向redis中添加哈希值

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

img


这是我的redis方法:

img


这是我的数据:

img

  • 写回答

3条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-06-06 14:03
    关注
    • 这有个类似的问题, 你可以参考下: 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正确添加对应的值,而不是仅添加最后一条值。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 6月14日
  • 已采纳回答 6月6日
  • 创建了问题 6月6日

悬赏问题

  • ¥15 from seleniumwire import webdriver 在抓取http://链接的时候会自动转https://这个怎么解决
  • ¥15 hive直连数据库模式插入mysql表数据失败(相关搜索:数据库)
  • ¥30 不会,学习,有偿解答
  • ¥15 SQL查询语句报错(检查)
  • ¥15 此表中公式应该怎么写
  • ¥15 求HI-TECH PICC 9.50 PL3安装包
  • ¥15 下载ctorch报错,求解
  • ¥15 如何入门学习c语言,单片机
  • ¥15 idea 编辑语言的选择
  • ¥15 Windows下部署Asmjit