注:以a+方式open乙個檔案的時候,write檔案是個原子操作,多程序之間不會出現交叉寫的情況,並且write大小沒有限制的,不受4k大小限制。
write乙個檔案核心是加鎖的,會保證原子執行。
ssize_t write(int fd, const void *buf, size_t count);
返回值代表寫了多少位元組,ret
一次write呼叫相當於原子地寫了ret位元組,因為write呼叫進入核心後會對fd加鎖。核心並不保****write寫完count位元組,但是寫了ret大小一定是原子寫的。他是核心加鎖的。
rename和a+的write都為原子操作,所以當write後才可以rename.但是要注意程式中要每次重新open檔案,不能一直使用同一fd.
在海量使用者環境中,很容易出現高併發應用程式同時向伺服器傳送請求的情況,有時候會因為傳送請求過於密集,致使伺服器負載過重,無法及時響應請求,即使伺服器能夠正常響應,也常常會產生一定程度上的延時,造成應用程式的等待,如果是互動程式的話,使用者的體驗就是網頁開啟很慢。針對這一種情況,有經驗的程式設計師一般都會考慮先將需要傳送的資料存放到佇列裡,然後agent讀取佇列的資料向指定伺服器傳送資料。這樣的好處有如下幾點
1、 非同步處理請求,可以有效減少應用程式尤其是互動程式的等待時間,上層應用只需要將請求放入佇列,即可以繼續往下執行其他任務
2、 應用程式可以脫離繁瑣複雜的底層通訊,提高開發效率,可以更好地進行分工協作
3、 可復用性,使用不同語言編寫的應用程式都可以使用同一佇列,避免了重複開發
4、 高效性,佇列可以針對網路通訊做一些有針對性的優化
5、 資料完整性,佇列可以採用動態排程,重傳等機制來保證資料能夠完整地傳送到目的地
佇列根據資料儲存方式不同一般可以分為
1、 基於共享記憶體的佇列
2、 基於檔案的佇列
讀取記憶體資料要比讀取硬碟資料快幾個數量級,所以基於共享記憶體的佇列要比基於檔案的佇列在資料讀取方面有優勢一些。但是基於共享記憶體的操作往往具有較高的複雜性和風險性,而且記憶體的容量是十分有限的,使用不當的話很容易造成out of memory。另外如果伺服器意外宕機的話,共享記憶體佇列裡面的資料將全部丟失,難以保證資料的完整性和永續性。
利用檔案來存放佇列資料,一般不用擔心空間容量的問題,因為檔案資料是存放磁碟上的,而且磁碟資料是持久的,不會因為異常宕機重啟後導致資料的丟失。一般多程序對同一檔案同時進行讀寫操作的時候都需要加鎖,但是在linux環境下可以通過追加寫以及rename的方式不加鎖對同一檔案進行讀寫操作,而且不用擔心會發生異常或者資料丟失。
應用程式可以將要傳送的資料以約定的格式存放到指定檔案裡,這裡值得注意的是必須是以a+追加寫的方式寫入檔案,因為在linux核心中,以追加的方式在底層是自動加鎖的。write底層是呼叫sys_write。而sys_write則是呼叫vfs_write,vfs_write的實現裡有下面一行:
ret = rw_verify_area(write, file, pos, count);
假設wrtie引數裡通知要追加200位元組(size_t count=200),當前尾端位移為offset,它會立即通過inode結構將offset ~ offset+200這個區域lock住。這時候任何其他想操作這個區域的程序將會阻塞,所以多個程序同時往檔案裡面寫資料是不會造成資料的紊亂的。(直接用open函式開啟,write函式寫入的話,就算資料大小超過4k,原子操作也是不會出現亂序問題的,如果用帶有快取的函式,如fopen開啟檔案,原子操作大小限制是4k)
也許有人會問,在不對檔案加鎖的情況下,多程序同時往檔案裡面寫資料也許沒問題,但是其他程序如何同時從檔案裡讀取資料呢?這裡可以通過 rename這個函式來實現,其他程序可先呼叫rename函式將佇列檔案重新命名為其他檔案,最好以時間戳作為檔名,這樣就不會產生檔案覆蓋的問題,然後該程序再去讀取重新命名後的檔案資料,此時每個程序只會讀取對應的唯一檔案,自然不會出現問題。
通過以上方法,多程序可以在不用對檔案加鎖的情況下讀寫同一佇列檔案,這樣能夠有效提高執行效率,而且減少了程式的複雜性。
多程序搶票不加鎖
code 檔案db的內容為 注意一定要用雙引號,不然json無法識別 併發執行,效率高,但競爭寫同一檔案,資料寫入錯亂 from multiprocessing import process,lock import time,json,random def search dic json.load ...
C 多程序檔案讀寫的鎖處理
隨著服務程序的增多,光憑程序內的執行緒同步已經不能滿足現在的需求,導致多程序同時寫入同乙個檔案時,一樣提示檔案被占用的問題。在這種場景下,跨程序級的鎖是不可避免的。在.net提供的參考中,程序鎖都繼承了system.threading.waithandle類 而在本文中針對單個檔案同一時間僅允許單個...
PHP解決多程序同時讀寫乙個檔案的問題
這個問題怎麼說呢,首先php是不支援多執行緒的,所以我想你應該說的是多程序吧,如果是對於檔案操作,其實你只需要給檔案加鎖就能解決,不需要其它操作,php的flock已經幫你搞定了。flock file,lock,block file 必需,規定要鎖定或釋放的已開啟的檔案 lock 必需。規定要使用哪...