thắc mắc Cách mà 1 server hoạt động

  • Người tạo chủ đề Người tạo chủ đề phuctienn
  • Ngày bắt đầu Ngày bắt đầu

phuctienn

Senior Member
Em chào các bác, em có các thắc mắc như sau mong các bác khai sáng cho em ạ

Câu hỏi 1:
- 2 máy cùng gọi đến 1 API. API này tốn 10s để thực hiện. Khi máy 1 vừa gọi API, máy 2 cũng gọi đến API đó, vậy máy 2 có phải đợi 10s để server trả xong kết quả cho máy 1 rồi mới thực hiện không. Nếu không thì server thực hiện chia thread hay như thế nào để có thể chạy song song trả kết quả về cho nhiều máy cùng lúc

Câu hỏi 2:
- Ví dụ 1 hàm thêm sản phẩm. Id của sản phẩm là tự động tăng. Để lấy Id vừa thêm thì ta phải lấy Id lớn nhất trong database. Vậy Id này có đúng không, trường hợp nhiều người thêm sản phẩm 1 lúc thì như thế nào (khi sản phẩm vừa được thêm vào db, cùng lúc đó nhiều sản phẩm khác của người dùng khác cũng được thêm vào db, vậy hàm lấy Id lớn nhất trong database có còn lấy được Id của sản phẩm vừa thêm không)

Hàm có dạng như dưới
C#:
Product InsertProduct(Product product) {
    _db.Products.Insert(product);
    var id = _db.Products.GetLastIndexInserted(); // Lấy Id mới nhất vừa được thêm
    product.Id = id;
    return product;
}
- Câu hỏi em thấy tương tự câu trên: Trong 1 hàm, gọi 2 lần hàm GetNewProducts để lấy danh sách sản phẩm mới nhất, 2 kết quả này có khác nhau không. Nếu giống nhau thì server thực hiện theo cơ chế nào
 
Sửa lần cuối:
java app server mỗi request sẽ có 1 thread ra xử lý, sau sẽ thêm vấn đề quản lý resource thread bác tự tìm hiểu thêm nhé,
còn nodejs thì queue nhận request chuyển qua worker thread tính toán, bao h xử lý xong kết quả thì bỏ lại vào queue để response.
e cũng newbie, có sai thì các bác vào sửa lại kiến thức cho e.
 
bạn tìm hiểu về multithread, synchronization primitive, deadlock, race condition... thì sẽ hiểu mấy cái kia nhé
 
Em chào các bác, em có các thắc mắc như sau mong các bác khai sáng cho em ạ

Câu hỏi 1:
- 2 máy cùng gọi đến 1 API. API này tốn 10s để thực hiện. Khi máy 1 vừa gọi API, máy 2 cũng gọi đến API đó, vậy máy 2 có phải đợi 10s để server trả xong kết quả cho máy 1 rồi mới thực hiện không. Nếu không thì server thực hiện chia thread hay như thế nào để có thể chạy song song trả kết quả về cho nhiều máy cùng lúc

Câu hỏi 2:
- Ví dụ 1 hàm thêm sản phẩm. Id của sản phẩm là tự động tăng. Để lấy Id vừa thêm thì ta phải lấy Id lớn nhất trong database. Vậy Id này có đúng không, trường hợp nhiều người thêm sản phẩm 1 lúc thì như thế nào (khi sản phẩm vừa được thêm vào db, cùng lúc đó nhiều sản phẩm khác của người dùng khác cũng được thêm vào db, vậy hàm lấy Id lớn nhất trong database có còn lấy được Id của sản phẩm vừa thêm không)

Hàm có dạng như dưới
C#:
Product InsertProduct(Product product) {
    _db.Products.Insert(product);
    var id = _db.Products.GetLastIndexInserted(); // Lấy Id mới nhất vừa được thêm
    product.Id = id;
    return product;
}
- Câu hỏi em thấy tương tự câu trên: Trong 1 hàm, gọi 2 lần hàm GetNewProducts để lấy danh sách sản phẩm mới nhất, 2 kết quả này có khác nhau không. Nếu giống nhau thì server thực hiện theo cơ chế nào
mai fen giống tui lúc mới học IT quá, nên để tui trả lời dựa theo hiểu biết của mình nhé.

Câu hỏi 1:
1. Tất cả thứ chạy trên máy tính đều là process
Ví dụ: có 1 file code như sau
print("Hello world") //code python nhé
thì khi chạy cái file code này phải sinh ra 1 process để in ra màn hình (dĩ nhiên ko đơn thuần là 1 process nhưng để đơn giản hóa cho fen hiểu)
2. Web Server thì cũng chỉ là 1 process thôi
server thực ra cũng giống cái file như trên thôi, nó sẽ nhận request tới và xử lý xong response lại cho client nên thằng tới sau phải đợi thằng tới trước cook.
Vậy thì để 2,3 client nó request vào cùng lúc thì lúc này mình phải tạo ra 2-3 cái process để xử lý song song HOẶC Multithreading để 1 cái process có thể handle nhiều client cùng lúc HOẶC dùng async (cái này nâng cao fen từ từ tìm hiểu cũng đc)
Thì cái việc "tạo ra 2-3 cái process" đấy rồi kết nối client nào tới process nào thì có software nó lo cho rồi, như php thì có php-fpm, còn Java thì hình như có Tomcat mình ko rõ lắm

Câu hỏi 2:
Mình ko biết cái function "GetLastIndexInserted()" trong example của fen nó code gì trong đấy.
Nhưng trong SQL thì mọi tương tác với DB đều được thực hiện trong transaction (phiên giao dịch), cho nên 2 thằng cùng insert vào cùng 1 table tuy nhiên nó lại nằm ở 2 transaction khác nhau nên có thể lấy đc ID mà mình vừa insert
Vd: trong mysql sẽ có command SELECT LAST_INSERT_ID()
 
Câu 1: trong java (cái khác mình chưa tìm hiểu) thì mỗi req sẽ cho một thread ra xử lý, được kéo ra từ pool để tái sử dụng. Mặc định thì nó sẽ xử lý song song (1 logical core handle 1 thread (trong lúc chờ thread này xử lý io thì thread khác có thể sd core) . Bạn có thể cấu hình cho thread và thread pool nhưng không thể động đến core (os xử lý). Vậy nên về cơ bản req này sẽ k phải đợi req khác
Câu 2: như # trên, mỗi lần query vào db đều dc bọc trong transaction (trong mysql hình như có cái cờ cho chức năng này, auto bật)
Trình intern mong các bác nhẹ tay ;(
 
Câu hỏi 2:
Mình ko biết cái function "GetLastIndexInserted()" trong example của fen nó code gì trong đấy.
Nhưng trong SQL thì mọi tương tác với DB đều được thực hiện trong transaction (phiên giao dịch), cho nên 2 thằng cùng insert vào cùng 1 table tuy nhiên nó lại nằm ở 2 transaction khác nhau nên có thể lấy đc ID mà mình vừa insert
Vd: trong mysql sẽ có command SELECT LAST_INSERT_ID()
Em cảm ơn bác ạ, câu 1 dễ hiểu lắm, còn câu 2 em tìm hiểu như thế này
1726743727794.png

  • Theo em hiểu: khi gọi 2 lần hàm GetNewProducts thì sẽ viết 2 câu query xuống db, mỗi câu query lại trong 1 transaction khác nhau nếu mình không gói vào 1 transaction => 2 dữ liệu nhận được có thể khác nhau.
  • Tương tự nếu không gói 2 transaction Insert và lấy LAST_INSERT_ID thì khi transaction của câu query _db.Products.Insert(product) thành công, trong quá trình chạy xuống transaction của câu query LAST_INSERT_ID có thể sẽ có nhiều user khác thêm product, và dẫn tới lấy sai Id của product vừa thêm

Không biết em hiểu vầy có đúng không ạ, hay còn cơ chế gì để gói các câu query trong 1 hàm vào 1 transaction to hơn để đảm bảo tính đúng đắn không ạ
 
Mình trả lời cho bạn.

Với cả 2 câu hỏi của bạn, nó phụ thuộc vào cụ thể server nào, database nào. Tùy vào điều kiện cụ thể mà mọi chuyện có thể được thực hiện khác nhau.

Ví dụ câu hỏi 1, nếu cái API đấy rất nặng chiếm hết tài nguyên của server thì lẽ dĩ nhiên cái sau sẽ phải chờ đủ 10s. Còn nếu server đủ khoẻ dĩ nhiên ko phải chờ. Còn việc thực hiện song song cụ thể ra sao thì toàn bộ framework cũng như hệ điều hành tự động lo hết cho bạn rồi ko cần bận tâm, có thể là thread, process... thậm chí nhỏ hơn cả thread nữa nếu bạn build mọi thứ customize cho việc handle request. Ví dụ đỉnh cao là Paypal chẳng hạn, nó có hàng tỷ transaction mỗi ngày mà chỉ cần 8 server, nói theo văn phong của anh Quảng là "thật ko thể tin nổi".

Câu hỏi 2 của bạn cái nó lấy lên hoàn toàn có thể ko phải ID vừa insert nếu bạn ko lock lại. Và logic lấy ID của bạn là sai bởi bản thân câu insert trước đó đã trả về ID của cái bạn vừa insert vào, tại sao lại còn GetLastIndexInserted nữa
 
Em cảm ơn bác ạ, câu 1 dễ hiểu lắm, còn câu 2 em tìm hiểu như thế nàyXem tệp đính kèm 2691460
  • Theo em hiểu: khi gọi 2 lần hàm GetNewProducts thì sẽ viết 2 câu query xuống db, mỗi câu query lại trong 1 transaction khác nhau nếu mình không gói vào 1 transaction => 2 dữ liệu nhận được có thể khác nhau.
  • Tương tự nếu không gói 2 transaction Insert và lấy LAST_INSERT_ID thì khi transaction của câu query _db.Products.Insert(product) thành công, trong quá trình chạy xuống transaction của câu query LAST_INSERT_ID có thể sẽ có nhiều user khác thêm product, và dẫn tới lấy sai Id của product vừa thêm

Không biết em hiểu vầy có đúng không ạ, hay còn cơ chế gì để gói các câu query trong 1 hàm vào 1 transaction to hơn để đảm bảo tính đúng đắn không ạ
mình nói về tổng quan toàn bộ quá trình giao tiếp với db của 1 process cho fen dễ hình dung
1. client đụng tới web server để kêu nó insert gì đó
2. web server sẽ kết nối tới DB (thằng này cũng là server luôn)
--> lúc này thằng webserver sẽ thành vài trò CLIENT so với DB server
3. mọi query (select,insert,update,delete) sẽ được thực hiện trong 1 transaction giữa thèn web và DB (dĩ nhiên webserver sẽ handle đc khi nào commit hay rollback transaction, fen tìm hiểu thêm nhé)
4. vậy thì ở số 1 thg client bắt thg webserver insert product A, thì vì thực hiện trong transaction nen DB sẽ ghi nhận dc cái insert này nên khi webserver chạy command Select Last_insert_id; thì DB sẽ trả về đc id của product A

tới đây nếu fen hiểu rồi thì, từ số 1 đến số 4 có hàng trăm cái process diễn ra song song như vậy thì thg DB vẫn sẽ trả về đúng cái id mà insert trong transaction đó.

Còn cái hàm GetLastIndexInserted mình nghĩ nó cũng đang dùng cơ chế mình nói ở trên thôi. Nếu ko sẽ dính phải vấn đề lấy nhầm ID của thằng khác như vấn đề fen băng khoăng đầu bài :D

Edit: hình như trả lời hơi lạc đề
cái fen ghi là hiểu đúng rồi đấy, do máy ko cài mysql nên ko tiện test nhưng hỏi chatGPT nó bảo nếu chưa insert cái gì mà chạy "Select LAST_INSERT_ID();" sẽ trả về 0
Cho nên để chạy được Select LAST_INSERT_ID(); thì phải chạy chung với câu insert trong 1 transaction nhé.
Vd trong mysql:
BEGIN TRANSACTION; // hoặc có thể set auto_commit=0
INSERT INTO test_table VALUES ("ten san pham","1000 ngan");
SELECT LAST_INSERT_ID(); // trả về ID của thằng trên
COMMIT;
 
Sửa lần cuối:
Em cảm ơn bác ạ, câu 1 dễ hiểu lắm, còn câu 2 em tìm hiểu như thế nàyXem tệp đính kèm 2691460
  • Theo em hiểu: khi gọi 2 lần hàm GetNewProducts thì sẽ viết 2 câu query xuống db, mỗi câu query lại trong 1 transaction khác nhau nếu mình không gói vào 1 transaction => 2 dữ liệu nhận được có thể khác nhau.
  • Tương tự nếu không gói 2 transaction Insert và lấy LAST_INSERT_ID thì khi transaction của câu query _db.Products.Insert(product) thành công, trong quá trình chạy xuống transaction của câu query LAST_INSERT_ID có thể sẽ có nhiều user khác thêm product, và dẫn tới lấy sai Id của product vừa thêm

Không biết em hiểu vầy có đúng không ạ, hay còn cơ chế gì để gói các câu query trong 1 hàm vào 1 transaction to hơn để đảm bảo tính đúng đắn không ạ
Cái bạn hiểu hoàn toàn đúng.

Chỉ là bạn ko hiểu Insert. Khi bạn insert data có field tự động tăng thì kết quả trả về của insert sẽ có giá trị của field đó trong đấy. Bạn ko cần cái LAST_INSERT_ID để làm gì.
 
Ví dụ bảng Product có data như sau:

ProductId | Price
1 | 100

Giả sử có 1 lệnh select
select * from Product where ProductId = 1

Và 1 lệnh update
update Product set Price = 200 where ProductId = 1

Trong trường hợp 2 lệnh cùng 1 thời điểm, không lệch một chút nào thì kết quả trả ra là gì?
 
kể cả có sát nhau đến từng mili s, thì nó cũng có cái gọi là queue thớt ạ, cái nào đến trước thì làm trước
 
Có chứ nhỉ ? Ví dụ cả triệu người đặt 1 cái order gì đó thì việc trùng tới ms mình nghĩ là có mà?
hệ thống quản lý csdl nó sẽ phải tuần tự hóa 2 lệnh của bạn, phụ thuộc theo độ ưu tiên của lệnh mà cái nào sẽ được thực thi trước hay sau thôi.
 
kể cả có sát nhau đến từng mili s, thì nó cũng có cái gọi là queue thớt ạ, cái nào đến trước thì làm trước
hệ thống quản lý csdl nó sẽ phải tuần tự hóa 2 lệnh của bạn, phụ thuộc theo độ ưu tiên của lệnh mà cái nào sẽ được thực thi trước hay sau thôi.
Vậy cơ chế là nó sẽ cho vào queue, rồi cuối cùng vẫn có cái trước có cái sau thím nhỉ
 
Có chứ nhỉ ? Ví dụ cả triệu người đặt 1 cái order gì đó thì việc trùng tới ms mình nghĩ là có mà?
nếu thực tế có trường hợp đó thì bọn dev nó cũng dùng cơ chế lock thôi, lệnh nào được đặt trước thì nó thực thi trước và lock lại, ok rồi mới tới lệnh sau
 
nếu thực tế có trường hợp đó thì bọn dev nó cũng dùng cơ chế lock thôi, lệnh nào được đặt trước thì nó thực thi trước và lock lại, ok rồi mới tới lệnh sau
Vậy giả sử có 1 vé trong database

Có rất nhiều người dùng cùng đặt mua vé cùng 1 lúc

Thì nên xử lý cơ chế này như thế nào các bác nhỉ?
 
Vậy cơ chế là nó sẽ cho vào queue, rồi cuối cùng vẫn có cái trước có cái sau thím nhỉ
chi tiết thì chắc thím phải chờ ông nào chuyên hơn về csdl họ trả lời.
mà vấn đề xử lý truy vấn cùng lúc mình nghĩ nó còn phụ thuộc vào việc bạn sử dụng hệ quản trị csdl nào nữa, chứ nói chung chung thì khó lắm, kiểu như thằng mssql nó sẽ xử lý khác với mysql hoặc postgres chẳng hạn.
 

Thống kê chủ đề

Ngày tạo
phuctienn,
Người trả lời cuối
seoitsystem,
Trả lời
49
Lượt xem
11.290
Quay lại
Lên đầu trang