【问题标题】:Distributed Locks for Spring + Hibernate + RedisSpring + Hibernate + Redis 的分布式锁
【发布时间】:2017-07-20 18:20:43
【问题描述】:

我一直在开发一个使用 Spring mvc + Hibernate 和 redis 进行缓存存储的多线程 Web 应用程序。我正在寻找一种将锁应用于控制器或服务的方法。

我无法使用 Hibernate 提供的锁定机制,因为它旨在应用于数据库级别。

这是一个例子:

@RestController
@RequestMapping(RestConstants.BASE_PATH + "/campaigns")
Class CampaignController  {

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public ApiResponse<?> findOne(@PathVariable Integer id) {
        Campaign campaign = repo.findOne(id);
        return toResponse(campaign);
    }

    @RequestMapping(value = "", method = RequestMethod.POST)
    public create(@RequestBody Campaign campaign) {
        //create an campaign here
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.PATCH)
    public update(@RequestBody Campaign campaign) {
        //update an campaign here
    }
}

@RestController
@RequestMapping(RestConstants.BASE_PATH + "/bulkCampaigns")
Class CampaignBulkController {
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public create(@RequestPart MultipartFile data) {
        /* 
        Data contains a list of campaigns with their details, 
         controller will iterate through the list and create all the campaigns.

         */
    }
}

在处理映射到 CampaignBulkController 中的 create 方法的请求时,无法处理对活动的所有其他写入,但允许读取。也就是说,应删除更新或创建活动/活动的请求。

有多个服务器,每个服务器都是多线程的。

我是 Spring 和 Hibernate 的新手,任何想法或建议都将不胜感激!

【问题讨论】:

  • 根据您的描述,听起来数据库级别正是您想要锁定的?锁定表,其他服务必须等待表解锁才能使用它。
  • 有两件事使它略有不同:1)当一个特殊请求正在处理中时,其他请求应该被丢弃,并且用户会收到一条消息,例如“无法处理您的请求,而 正在处理中,请稍后再试。2)我需要确保当有请求进来时,只有在处理特殊请求时才会丢弃它。
  • 特殊请求是否与非特殊请求共享表?特殊请求是特定操作,还是常规操作,但带有一些特殊标志来指示它们需要区别对待?您应该编辑您的问题并提供一些示例,说明您可以拥有什么样的用例。
  • @Kayaman 我刚刚更新了我的问题,如果您需要更多详细信息,请告诉我。谢谢!

标签: java spring multithreading hibernate locking


【解决方案1】:

我将在这里概述一个初步的答案,可能供以后修改。

如果您使用共享的ReadWriteLock 并为常规操作使用读锁,您可以让您的特权操作使用写锁来阻止常规操作。

// Regular operation tries to lock, if not successful a privileged operation is happening
if(!lock.readLock().tryLock())
    return cannotProcessResponse;

performRegularOperation();
lock.readLock().unlock();

// Privileged operation always waits for lock
lock.writeLock().lock();
performPrivilegedOperation();
lock.writeLock().unlock();

现在这种方法存在一些问题。如果使用单个共享锁,则一次只能运行一个特权操作。如果这是一个问题,可以使用多个锁并将它们的读锁锁定在一起(这可能容易出现死锁,因此必须小心)。还应考虑锁公平性。

【讨论】:

  • 我刚刚更新了我的问题,因此多个特权操作也不能同时运行。您建议如何实施锁定?
  • 这样更简单。只需使用共享锁(例如将其作为 bean 注入)并按照我在回答中概述的方式进行操作。当然,在盲目复制我的代码之前,请先阅读大量内容。
  • bean 线程安全吗?我可以跨多个线程和多个 Web 服务器实例仅声明一个 bean 吗?
  • 你没有提到你有多个服务器。然后,您必须获得某种外部锁定提供程序。您还需要更多地了解 Spring,因为“是 bean 线程安全”没有多大意义。
  • 看来我需要从现在开始做更多的研究,但是谢谢! :)
猜你喜欢
  • 1970-01-01
  • 2021-11-05
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-11
  • 1970-01-01
相关资源
最近更新 更多