見出し画像

【kintone】楽観排他制御でも在庫管理がしたい! ~パート2~

パート1の記事はこちら

前回までのあらすじ

在庫管理には同時操作性と厳密な数量管理が必要だ。
だが僕たちにはクライアントサイドでの楽観排他制御しかなかった。
衝突するレコード。圧迫される通信帯域。
サービス提供会社からのリクエスト数制限警告メールが
担当者の心を締め付ける。
次回、楽観排他制御でも在庫管理がしたい!
僕たちは道を間違ってしまったのか・・・?

そもそも排他制御が必要なの?

気でも狂ったのか?と思われるかもしれませんが、結局のところ、問題が発生するのは排他制御がかかることにあります。これをなくしてしまえば問題は発生しないのでは!?

いまいちど、排他制御がかかる処理について整理してみようではありませんか。

データ概念図

さて、データ構造を見ると、処理対象データは「在庫マスタ」と「入出庫台帳」であることはわかると思います。

在庫マスタの在庫数の更新処理にて、排他制御がかかるのでした。つまり、在庫数(理論在庫)の更新を実施している点です。

では逆に考えてみますと、「入出庫台帳」には排他制御がかからないということが言えます。そうです。入出庫台帳は対象にならないのです。

在庫のレコードは衝突する
作業のレコードは衝突しない

CRUDとはデータベースの基本操作のことで、
C:Create:登録
R:Read:読み取り
U:Update:更新
D:Delete:削除
を指します。この4操作を考えてみます。

入庫処理を考えると、在庫マスタには在庫数をUpdateをしていることに対して、入出庫台帳にはCreateを実施していることが分かると思います。Createはその時初めて作られるわけですから、排他制御は必要ないですね。

入庫の修正処理も、どうでしょうか?
この場合も、入庫レコード新しいデータでUpdateすれば大丈夫です。なぜなら作業とレコードの対応から、複数の不特定な更新を同時に受けないからです。しかし在庫レコードは数を引かなければならないので、不特定多数の処理からUpdateする必要がありますから、排他制御が必要です。

はい。つまり、データベースのUpdate処理だけが排他制御の対象になるということです。だから不特定多数からのUpdate処理を排除できれば、排他制御の悪夢(?)から解放されるのです。

在庫とは何か

在庫(理論在庫)とは何でしょうか? 数式から考えてみます。

理論在庫 = 現在の在庫数 - 入出庫数

となります。「現在の在庫数」が排他制御の対象になっている在庫レコードになりますね。

ここで、現在の在庫数は「その前の理論在庫」です。

では、n回目の作業時の理論在庫は、

理論在庫(n) = 理論在庫(0) + 入出庫数(0) + 入出庫数(1) + ・・・+ 入出庫数(n - 1) + 入出庫数(n) 

となりますから、入出庫の記録がちゃんとそろっていれば、計算の初期値の理論在庫があれば計算値で出せます。しかもただのたし算で!

計算の初期値の理論在庫(0)とは、棚卸在庫数のことですよね!

つまりこんな感じの入出庫台帳を作ることができればいいわけです。

全部の記録を1つの実体へかさねる
理論在庫数は計算値で出す

つまり、在庫マスタデータを実体表(テーブル/アプリ)にせずに、導出表とします。

これで排他制御を追い出すことができますね!! やったぜ!

kintoneでどう作る?

さあ、理論はわかりました。ここからは実践です。イメージ通りの内容をkintoneで実現できるでしょうか?

入出庫台帳は項目を工夫すれば、なんとかできそうです。単純にデータが積み重なっていくアプリですからね。

では理論在庫ビューはどのように作りましょうか?

ここはkintoneの集計機能を使ってみましょう。

アプリはこんな感じ
合計値もたし算だけで出せますね
集計対象になるかどうかは「集計」フラグで

SQLが投げられるなら「区分=棚卸在庫」のレコードをとって、それ以前の記録日時のレコードをセットから外すといったことができますが、kintoneでは難しいので、簡単に「集計」項目を作って集計対象を指定しています。

このようにして、導出表を(制限はありつつも)作成することができました。

そもそも在庫量をリアルタイムに把握する必要があるか

おいおい!とおっしゃりたいかもしれませんが、在庫マスタもいらない!と捨ててしまった我々ですから、ここはいま一度考えてみましょう。

実際は安全在庫の考えから、在庫数ギリギリまで販売する、出庫をかけるということは絶対ないですよね。

在庫とは物流のうち滞留している状態を指すので、実際に本当に必要なのは1)予測すること
2)トレースすること
の2つになるはずです。

予測に関しては、「販売したいけど、在庫が足りるかな?」とか、「生産命令出したいけど、原料/部材足りるかな?」とかですね。

トレースは、「問題が起こったけど、あの時どうだったかな?」ということです。

そのなかで「リアルタイム」とは、物や状態のリアルではなく業務の要請に対するリアルが実現できればいいわけです。

kintoneのグラフ機能で在庫表を実装しましたが、「検索」や「項目数の制限」という意味で、課題を抱えていますね。

なので、グラフの内容を別のアプリに移す外部バッチ処理を組みましょう。

これはkintone単体では実現できませんが、外部サービス・・・krewDataなどの専用サービスやAWS/Azure/GCPなど汎用のクラウドサービスで実現できます。お客様の環境を借りてもよいですし・・・。

このバッチ処理のスケジュールの実行間隔を調整してあげれば、kintoneのアプリに「在庫量」を連携してあげることができます。

kintoneの標準機能でCSVでグラフを出力して、そのまま読み込ませるとこんな感じ


できたはいいが・・・

さあ、具体的なkintoneアプリもできました。ではこのアプリは運用できるのでしょうか?

いくつか出そうな要望を考えてみます。

1)集計の"無効"をセットするのがめんどくさい
2)棚卸在庫データ+入出庫記録でデータの量が多すぎる
3)未入荷、未出荷を反映して、将来の在庫量を見たい

うーん。どの要望も難しそう・・・。少なくともkintone単体の機能ではこれらの要望に応えることはできません。

集計の"無効"をセットするのがめんどくさい

これは・・・絶対出ますね。
棚卸業務に組み込めればいいですが・・・難しそうです。

バッチ処理組むしかないですね。棚卸に関するアプリも作ることになるでしょうから、機能をそちらに組み込むことになるかと思います。

実際にアプリを作るなら、集計対象以外は不要なデータとして圧迫しているので、別のアプリに逃がしたいところ。でもやったらやったで、「1つのアプリで検索できるようにしてほしい」って現場の方は言いそうですね。

半リアルタイムでよければ、先ほど作った在庫アプリで逃げられますね。

棚卸在庫データ+入出庫記録でデータの量が多すぎる

これは商品、置場ごとにアプリ分割する一手ですね。

カスタマイズをするにしても、データの取得に多大な時間がかかるようになりますから、データ量を意識して最初の設計から考える必要があると思います。

データ量はどんな案件でも初めにヒアリングする項目ですから、作る前に考えておかなければいけませんね。

未入荷、未出荷を反映して、将来の在庫量を見たい

これは、入出庫台帳に将来の入出庫レコードを立てれば見ることができます。ただ、往々にしてこういう要望をおっしゃる利用者の方はダッシュボードのような「見た目」を要求しています。

kintoneでダッシュボードを作成するにはプラグインや外部サービスの力を借りる必要があるかもしれませんね。

落としどころを見つける技術

いつの間にかkintone前提で記事を書いていましたが、結局のところどんなSaaSでも、そのサービスの独特の制限値とプロジェクトの予算に折り合いをつける必要が出てくると思います。

サービスの制限値や得意不得意を現場と交渉できるかどうか。そして交渉には説得力と真心と精神力が必要です。

なぜこのような作り/画面になるのか。なぜ操作がひと手間必要になるのか。説明を続けることが要求されます。

心が折れてしまって、「もう排他制御いいや。リビジョン使わずにダーティに更新してやれ。データがおかしくなってもいいや。」となってしまうと、関わる人がみな不幸になりますから。

結局、楽観排他制御で在庫管理できるのか

どうなんだい!?

答えは「できる!」だと思います。

しかし、在庫管理の実際の業務は各社で違いが出るし、各現場でも独特だったりするので、「在庫管理システムに要求される内容が」実現可能かどうかはまた吟味する必要があります。

在庫管理は専用パッケージもあるし、会計/販売管理に組み込まれていることもあります。そうなるとパッケージ同士の連携も・・・。

まとめ

そういったわけで、やっていることは簡単なのに、現実は難しい在庫管理システムのお話でした。

このお話のポイントは

1)サービスの楽観排他制御を在庫管理と両立させるには独特の問題がある
2)排他制御を避けるアーキテクチャは存在する
3)アーキテクチャ特有の実装方針がある
4)実装方針について説明を求められる

ということでした。


この記事は以上です。お読みいただきありがとうございました。


この記事が気に入ったらサポートをしてみませんか?