Asked Mar 28th, 2021 7:08 a.m. 157 0 5
  • 157 0 5
0

[Laravel] xử lý dữ liệu cùng một thời điểm

Share
  • 157 0 5

Mình có 1 hàm rut tiền khi trong tài khoản có tiền như này ( hàm ruttien) Người A tiền hành rút tiền.

function rutien(Resquest  $r){
$a = NhanVien::where('id',$r->ID)->first();
	$luong = $a->luong;
	if($luong>0){
		$daily->decrement('luong',$luong);   
}

Nhưng cùng tại thời điểm đó thì người B, tiến hành hàm gửi tiền cho người A

function tangdiem( Resquest  $r){

$b = NhanVien::where('id',$r->id)->first();
$sotien = 100; 
$b->increment('luong',$sotien);   
}

Lỗi của mình gặp phải là nếu A và B làm 2 thời gian lệch nhau thì ok, ngon lành không vấn đề gì, nhưng nếu cả hai cùng làm 1 thời điểm thì nó gặp phải lỗi hieur sai vấn đề, có nghĩa hàm rút tiền nó sẽ trừ nhiều hơn số tiền hiện có, làm cho số tiền của người A sau khi rút sẽ bị âm xuống.

Không hiểu mình bị sai chỗ nào mà gây ra chuyện này nhỉ, và có thể cho mình phương án xử lý . Thanks All.

5 ANSWERS


Answered Mar 28th, 2021 11:12 a.m.
0

Cái hàm so sánh kia thì ăn thua gì thím.

ví dụ số dư là 20k, 2 lệnh rút tiền cùng lúc thì phép so sánh >0 đều pass thôi 😄

Làm cho cái hàm rút tiền đó chạy tuần tự (lock chỉ có 1 process chạy hàm này vào 1 thời điểm: cho vào queue rồi dùng 1 chạy chẳng hạn)

Share
Avatar TinhTN @tinhtn89
Mar 28th, 2021 4:10 p.m.

Mình hiểu ý bạn, nhưng có thể nói rõ hơn làm sao để biết cái nào đang chạy , để lock 1 cái chạy 1 cái .

0
| Reply
Share
Answered Mar 29th, 2021 3:44 a.m.
0

@tinhtn89 Bạn thử đối ứng nó bằng queue nhé.
Tham khảo doc: https://laravel.com/docs/8.x/queues#introduction
Thay vì request rút tiền đến, bạn sẽ xử lý cho phép rút tiền ngay.
Thì bạn dispatch 1 lệnh rút tiền vào trong queue.
Tương tự với hàm gửi tiền cũng thế.
Queue giúp bạn đảm bảo được, mỗi thời điểm chỉ có 1 job rút tiền hay gửi tiền đc chạy.

Tiện thể bạn đặt tên hàm là tăng điểm à 😄 tangdiem
Cố gắng đặt lên dễ hiểu xíu nữa nhé.

Share
Avatar TinhTN @tinhtn89
Mar 29th, 2021 5:23 a.m.

Cảm ơn bạn, Mình viết tên hàm đó cho ae dễ hiểu thôi, tangdiem = tặng điểm 😃 Về cơ chế thì mình hiểu nhưng vẫn chưa biết cách viết như nào?

0
| Reply
Share
Avatar iamfresher @benkyou
Mar 29th, 2021 6:12 a.m.

@tinhtn89 Bạn cứ lấy hướng dẫn gửi mail này làm ví dụ này.
https://rathorji.in/p/laravel_76_queue_tutorial_laravel_76_send_mail_with_queue_example Thì bài toán trên của bạn cũng tương tự như vậy.
Nói queue sang miệng thế thôi, thực ra nó tạo trong db của bạn thêm 1 bảng, để đăng ký các job vào đó.
Sau đó cứ xử lý xong thì nó xóa đi.
Rồi tìm tới record tiếp theo để xử lý.

0
| Reply
Share
Answered Mar 30th, 2021 1:29 a.m.
0

Theo mình bạn nên tìm hiểu thêm về transaction db và queue. giả sử trong trường hợp hết điện ở cái đoạn trừ tiền thì sao

Share
Answered Apr 1st, 2021 9:35 a.m.
0

Bạn tìm hiểu thằng này thử xem https://laravel.com/docs/8.x/queries#pessimistic-locking Ý tưởng là lock bản ghi lại, cho đến khi process khác xử lý xong

Share
Answered Apr 5th, 2021 9:28 a.m.
0
  1. đây là bài toán transaction nên dùng các database có cơ chế lock khi update/insert, ví dụ như mysql
  2. sử dụng cơ chế lock database để xử lí, bạn tham khảo bài này xem: https://viblo.asia/p/mysql-table-locking-yMnKMjjaZ7P
Share
Viblo
Let's register a Viblo Account to get more interesting posts.