-
1 # 合肥隔壁科技
-
2 # ksfzhaohui
什麼是髒資料,髒資料就是過期的資料;
為什麼會出現髒資料,根本原因還是資料沒有同步,歸根結底其實就是資料一致性問題,怎麼保證資料的一致性這本身就是一個難題;我們平時會遇到哪些髒資料的情況,該如何解決;
1.多執行緒同時操作變數
比如多個執行緒同時操作一個變數,有執行緒set值,有執行緒get值;如果不用synchronized等關鍵字會出現髒資料的情況;這主要和java的記憶體模型有關;
2.操作資料庫導致髒資料
比如同時往資料庫插入兩條記錄,如果沒有事務來保證資料同時成功和同時失敗,就可能會出現髒資料;
3.快取髒資料
比如我們經常會用到快取,儲存資料庫的時候儲存一份到快取中,更新資料庫的時候也同時更新快取,這樣取資料的時候直接從快取獲取資料即可;如果不能保證資料同步快取和資料庫也會出現髒資料;
4.分散式事務
比如最常見的跨行轉賬問題,如果沒有分散式事務,就可能出現髒資料;
5.資料同步
資料同步可以說是資料一致性問題最好的例子了,比如mysql主從同步,zk資料同步;這其實要牽扯出一個基礎理論CAP理論,主要內容如下:
一個分散式系統不可能同時滿足一致性(Consistency)、可用性(Availability)和分割槽容錯性(Partition tolerance),為什麼這麼說其實可以給出證明的:
這裡可以做一個簡單的證明:
前提:對於一個分散式系統而言,分割槽容錯性可以說是一個最基本的要求。因為既然是一個分散式系統,那麼分散式系統中的元件必然需要被部署到不同的節點,否則也就無所謂分散式系統了;
假設網路中有2個節點N1和N2,N1和N2上分別安裝了資料庫D1(主)和D2(備)形成主備模式,D1(主)負責寫並且讀,D2(備)分擔一部分讀
正常情況下:D1(主)寫完資料,同步到D2(備),讀取D2可以讀到最新的資料
非正常情況下:作為一個分散式系統,它和單機系統的最大區別,就在於網路,現在假設一種極端情況,N1和N2之間的網路斷開了;D1(主)寫完資料,D2(備)沒有更新到最新的資料;這時候怎麼辦,有2個選擇:第一,犧牲資料一致性,響應舊的資料給使用者;第二,犧牲可用性,阻塞等待,直到網路連線恢復,資料更新操作完成之後,再給使用者響應最新的資料。
所以可以看到主流的一些中介軟體在資料一致性問題上其實都是在AP和CP直接抉擇的,比如zk更傾向於CP,eruaka更傾向於AP;
更多可以關注本人的相關文章:
從ACID到CAP/BASE
https://www.toutiao.com/i6748644401506943499/
2PC/3PC到底是啥
https://www.toutiao.com/i6748710371780985348/
Paxos演算法淺析
https://www.toutiao.com/i6748725707750244877/
回覆列表
髒資料(Out-of-date data),指過時的資料。
如果在您的Java程式中存在髒資料,將或多或少地給軟體系統帶來一些問題,如:無法實時地應用已經發生改變的配置,軟體系統出現一些莫名其妙的、難以重現的、後果嚴重的錯誤等等。儘量避免髒資料的存在是非常有價值的。
Fragment 1。 快取技術的髒資料問題
/**
* A report printer is used to print a report。
*
* @version 1。0 9/9/2003
* @author Bill
*/
public class ReportPrinter
{
/**
* Constructs a ReportPrinter instance。
*/
public ReportPrinter()
{
// do something。。。
}
/**
* Prints a printable。
*
* @param printable the specified printable object
*/
public void print(Printable printable)
{
Graphics g = getGraphics();
g。
setFont(getReportFont(printable。getFont());
printable。print(g);
}
/**
* Returns the corresponding report font of a java font。
*
* @param javaFont the specified java font
* @return the corresponding report font
*/
private Font getReportFont(font javaFont)
{
Font reportFont = fontMap。
get(javaFont);
if(reportFont == null)
{
reportFont = loadFont(javaFont);
fontMap。put(javaFont, reportFont);
}
return reportFont;
}
/**
* Loads the corresponding report font of a java font。
*
* @param javaFont the specified java font
* @param the corresponding report font
*/
protected static Font loadFont(Font javaFont)
{
Font reportFont = null;
// do something。
。。
return reportFont;
}
/**
* The font map(java font->report font)。
*/
private static HashMap fontMap = new HashMap();
}
Fragment 1中,由於裝載一個java font所對應的report font開銷較大,使用了快取技術來避免這種開銷。
這是一種常見的提高效能的方式,而且在一般情況下執行良好。但是Fragment 1的設計與實現可能是不完備的,因為極有可能一個java font所對應的report font在系統啟動之後發生變化,在這種變化發生之後,只有重啟軟體系統才能裝載之,這常常是終端使用者的抱怨之一。