php的在頁面載入時(shí)或調(diào)用session_start()時(shí)從數(shù)據(jù)源中讀取session數(shù)據(jù)到$_SESSION變量。
創(chuàng)新互聯(lián)是一家專業(yè)從事網(wǎng)站制作、成都網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司。作為專業(yè)網(wǎng)站設(shè)計(jì)公司,創(chuàng)新互聯(lián)依托的技術(shù)實(shí)力、以及多年的網(wǎng)站運(yùn)營經(jīng)驗(yàn),為您提供專業(yè)的成都網(wǎng)站建設(shè)、全網(wǎng)整合營銷推廣及網(wǎng)站設(shè)計(jì)開發(fā)服務(wù)!
當(dāng)頁面執(zhí)行完畢或調(diào)用session_write_close()時(shí)把$_SESSION變量寫入數(shù)據(jù)源。
php默認(rèn)的session.save_handler=files,可以通過文件鎖來實(shí)現(xiàn)讀寫同步,保證session數(shù)據(jù)的一致性,不會(huì)產(chǎn)生問題。然而當(dāng)使用sqlite作為session handler時(shí),由于沒有同步機(jī)制,會(huì)產(chǎn)生bug。如下代碼:
test1.php
PHP code?
session_start();
$_SESSION['data1'] = 'data1';
sleep(10);
session_write_close();
test2.php
PHP code?
session_start();
$_SESSION['data2'] = 'data2';
session_write_close();
在同一瀏覽器進(jìn)程里(保證使用相同的session_id),先訪問test1.php,再訪問test2.php,會(huì)發(fā)現(xiàn)data2根本沒有寫入sqlite數(shù)據(jù)庫中。session.save_handler=memcache還沒有測(cè)試,估計(jì)也有這個(gè)問題。如果采用默認(rèn)的files handler會(huì)發(fā)現(xiàn)test2.php的請(qǐng)求會(huì)被掛起直至test1.php執(zhí)行完畢,這就是文件鎖同步機(jī)制造成的。
我想到了兩種解決方案:
1、實(shí)現(xiàn)互斥鎖,保證同一session_id訪問session數(shù)據(jù)是同步的,這樣會(huì)產(chǎn)生一個(gè)阻塞的問題(php默認(rèn)的session實(shí)現(xiàn)也會(huì)有這個(gè)問題)。
2、寫入session數(shù)據(jù)時(shí)進(jìn)行數(shù)據(jù)合并,不過這樣仍然不能完全保證數(shù)據(jù)一致性。
你說的應(yīng)該是mysql的事務(wù)機(jī)制,修改不同表數(shù)據(jù)的時(shí)候,要么同時(shí)成功,只要有一條失敗都不能算成功,你可以用php手動(dòng)開啟事務(wù),可以這么寫
$mysqli-query("START?TRANSACTION");
$mysqli-query("INSERT?INTO?a(field1)?VALUES?('a1')");
$mysqli-query("INSERT?INTO?b(field2)?VALUES?('a2')");
$mysqli-query("commit");
大概格式就是這樣,希望對(duì)你有幫助
不會(huì),這里的原子性不要從php的角度看,應(yīng)該從redis的角度看,同一個(gè)redis節(jié)點(diǎn)對(duì)并發(fā)的請(qǐng)求都是序列化處理的,所以單操作不存在你擔(dān)心的并發(fā)問題,但如果是read write的形式到哪里都不行了,切記。
有人問到read write是啥,其實(shí)就是并發(fā)的一個(gè)經(jīng)典問題,代碼如下
$v = $redisClient-get('v');
$v ++;
$redisClient-set('v', $v);
就是先讀取數(shù)據(jù),再修改數(shù)據(jù),在寫回修改,這里是希望每次訪問都遞增v的值,但在并發(fā)情況下,兩個(gè)進(jìn)程都讀取到了一樣的初始值,比如3,然后都加1變?yōu)?,最后把4寫回Redis,這種情況就會(huì)統(tǒng)計(jì)數(shù)據(jù)比實(shí)際的少。盡量都用Redis的原子操作就好,比如incr。