2
I’m thinking of migrating my ERP (currently in java) from a relational database (currently in Firebird) to a Nosql (probably Mongodb). I am planning and trying to anticipate the possible problems. The goal is to build a control that never let the quantity of the item become negative. I still have the ACID bias, which makes this migration difficult. I managed to solve all problems of the rest of the system, but there are still 2 situations in the stock control that today are solved with triggers.
Problem 1
One order with 2 items (quantity ball = 2 and quantity chair = 1) and there is not enough quantity in the stock (quantity ball = 1 and chair = 0) to complete the order stock move. As soon as I try to move the order stocks, I run a loop to download the stock amount of each item, one by one. Consequently, there would be a failure in the drive by not having enough stock and the rollback would happen. In the case of Mongodb, each 'document' would be equivalent to an amount of an item to decrease, that is, there is no transaction between documents in Mongodb.
Problem 2
In a word: competition. Suppose there are no triggers controlling this scenario, only select
returning the current amount and a if
to say whether there is quantity or not, item by item. The first user sees the quantity of sufficient stock (ball quantity = 2, chair quantity = 1) and the system releases the stock movement and the order completion. But while the first user transaction is running, a second user tries to make the same move, but as the first transaction has not yet finished, the second user also sees ball quantity = 2, chair quantity = 1 when consulting the stock, and the system also releases (erroneously) the stock movement. Consequently, the chair would be lowered twice when it could only be 1 time, and I end up with negative stock.
I saw some alternatives as stock reserve but I don’t think they fit for me. Please don’t think of an e-commerce or PDV. Think of a big warehouse full of reels that weigh 1 ton and cost 1 million reais each, and that can not be moved easily nor have stock reserved (because of business rules). In addition, with 1000 branches spread across the country with 10 sellers each trying to move the same items. Think of ten thousand clicks per minute.
Initially I thought about isolating only the stock movement function in Firebird, but I think it can’t handle ten thousand clicks per minute.
I even made a test: I made an application with Spring Boot and Firebird to make these moves. To test this competition demand, I used Jmeter and put 100 users (the goal is 10000) who try to make this movement, without starting interval between them. I managed at most 9 concurrent operations successfully moving stock of the same items. Firebird returns error:
'deadlock, update conflicts with concurrent update....', 'SQL Error: 335544336, SQLState 40001'
I am using Firebird 3, Debian 9, Java 8 and Hibernate 5.0.11.final.
I’ve been reading and thinking, and if I use Apache Kafka Transaction Streams with Mongodb? Will Kafka can queue the requisitions so that I can test the quantity of all the order items before moving, and only move if there is stock. And only then process the next move request. Is this possible?
How to build this system/functionality with Nosql meeting these requirements? Or how to build with Firebird, but considering the result I got with Jmeter?
To me it seems the kind of problem that gets better in SQL. If you need some extra fields that need features Nosql could use a base that accepts this, such as Postgresql with its type "JSONB". This bank still has the advantage of having the performance you need.
– jsbueno
Reading your requirements/tests I remembered this one page of the Mongodb documentation. I agree with Victor Stafusa’s considerations in his answer, it is to evaluate a hybrid approach, because this documentation solution should add a lot of work in the end. Now if competition is critical as well as consistency, take a look at the proposal there.
– Jorge C. Bernhard Tautz