Search code examples
javain-memory-database

Best option for in memory data management


Background: I'm working on a web-based application built in Spring MVC and Angular. we have a help desk module where agents use to work for customer care. The application is deployed on a single server. we have a ticket locking mechanism i-e when an agent opens a ticket to start working on it ticket get locked to that agent so that other agents may not work on the same ticket at the same time. as soon as the agent closes the ticket its available for other agents to open and update if needed. For locking ticket to avoid too much DB calls we have implemented ConcurrentHashMap so that everyone gets updated for the locking ticket using the same map this is working absolutely fine.

Issue: Now the application is deployed on two different servers and this ConcurrentHashMap is not working as MAP is maintained by each server. If a user is locking a ticket using Node-1 and if 2nd user's request goes to node-2, this approach is not going to work. To avoid this situation we are planning to change the flow so that we may avoid such issues. Parallelly, we don't want to save this locking details directly to DB to avoid DB IO as it a very frequent usage area of application.

Options After doing some R&D I got the following options that we can implement, keeping the persistence in mind.

  1. We can implement the In-Memory table concept using MSSQL or Redis
  2. RabbitMQ
  3. We can implement an API that will be deployed on a single node and both of our servers will use that to maintain locking tickets but we still have two problems with this calling API would be time taking and 2nd it's not persisting the data, if the server will get restarted we will lose the data.

Can anyone advise me on which approach should be good for the above case and how to implement it. I just need a startup.

thanks in advance.


Solution

  • I think your real problem is this:

    For locking ticket to avoid too much DB calls [ you decided not to use the database ].

    IMO, that was a mistake. A database call to acquire a "lock" on a ticket is unlikely to result in too many database calls.

    In analyzing this, you need to consider how often someone will want to start working on a ticket, and how often it is likely to fail because someone is already working on the ticket. I don't know your use-case details, but I would be very surprised if the latter event happens more often than once per second.

    If your database cannot sustain one "small" database operation per second (worst case!) for locking, then it won't be able to sustain the larger transactions involved in creating tickets, agents updating them, user reading them, and so on.

    So suggestions are:

    1. Work out what the actual database load for ticket locking will be ... relative to all of the other things that the database needs to do.

    2. If it is small, just go back to the database for ticket locking. Keep it simple!

    3. If it is large; either:

      • Scale up or scale out the existing database; e.g. use sharding. It seems likely that you will need to do this anyway. That should give you the "headroom" to use the existing database for locking as well.

      • Create a separate database server for the locking. It is unlikely that it will need to be big, and I can't envisage that it needs to be very fast. (See below!!)

      • Use one of your proposed solutions.


    But my main advice is to AVOID the trap of premature optimization. You seem to be designing for bottlenecks that you think will exist without any clear evidence for this. For example:

    "We can implement an API that will be deployed on a single node and both of our servers will use that to maintain locking tickets but we still have [the problem] with this calling API would be time taking ..."

    Unless the time taken is multiple seconds, this is unlikely to be a real problem. The best strategy is to implement the system first the simple way and then measure performance to see 1) whether optimization effort is warranted and 2) where the real bottlenecks are in the complete system.

    In your case, I doubt that the users will care if it takes (say) 1 second versus 2 seconds to be told that someone else is already working on a ticket.


    Finally, wouldn't it be simpler to use an existing off-the-shelf ticketing system? There are many of them out there. Commercial products, open source, hosted, etcetera. (OK it is probably too late for this, because it sounds like you are committed to implementing your own ticketting system from scratch. But it may not be too late to reconsider your strategy.)