并發(fā)安全就是程序在并發(fā)的情況下執(zhí)行的結(jié)果都是正確的;
Go中數(shù)據(jù)類型分為兩大類:
字節(jié)型、布爾型、整型、浮點(diǎn)型取決于操作系統(tǒng)指令值,在64位的指令集架構(gòu)中可以由一條機(jī)器指令完 成,不存在被細(xì)分為更小的操作單位,所以這些類型的并發(fā)賦值是安全的,但是這個(gè)也跟操作系統(tǒng)的位 數(shù)有關(guān),比如int64在32位操作系統(tǒng)中,它的高32位和低32位是分開(kāi)賦值的,此時(shí)是非并發(fā)安全的。
復(fù)數(shù)類型、字符串、結(jié)構(gòu)體、數(shù)組,切片,字典,通道,接口, 這些底層都是struct,不同成員的賦值 都不是一起的,所以都不是并發(fā)安全的。
單例模式的作用是確保無(wú)論對(duì)象被實(shí)例化多少次,全局都只有一個(gè)實(shí)例存在。根據(jù)這一特性,我們可以將其應(yīng)用到全局唯一性配置、數(shù)據(jù)庫(kù)連接對(duì)象、文件訪問(wèn)對(duì)象等。
餓漢式實(shí)現(xiàn)單例模式非常簡(jiǎn)單,直接看代碼:
package singletontype singleton struct{}var instance = &singleton{}func GetSingleton() *singleton { return instance}
singleton 包在被導(dǎo)入時(shí)會(huì)自動(dòng)初始化 instance 實(shí)例,使用時(shí)通過(guò)調(diào)用 singleton.GetSingleton() 函數(shù)即可獲得 singleton 這個(gè)結(jié)構(gòu)體的單例對(duì)象。
這種方式的單例對(duì)象是在包加載時(shí)立即被創(chuàng)建,所以這個(gè)方式叫作餓漢式。與之對(duì)應(yīng)的另一種實(shí)現(xiàn)方式叫作懶漢式,懶漢式模式下實(shí)例會(huì)在第一次被使用時(shí)被創(chuàng)建。
需要注意的是,盡管餓漢式實(shí)現(xiàn)單例模式的方式簡(jiǎn)單,但大多數(shù)情況下并不推薦。因?yàn)槿绻麊卫龑?shí)例化時(shí)初始化內(nèi)容過(guò)多,會(huì)造成程序加載用時(shí)較長(zhǎng)。
接下來(lái)我們?cè)賮?lái)看下如何通過(guò)懶漢式實(shí)現(xiàn)單例模式:
package singletontype singleton struct{}var instance *singletonfunc GetSingleton() *singleton { if instance == nil { instance = &singleton{} } return instance}
相較于餓漢式的實(shí)現(xiàn),懶漢式將實(shí)例化 singleton 結(jié)構(gòu)體部分的代碼移到了 GetSingleton() 函數(shù)內(nèi)部。這樣能夠?qū)?duì)象實(shí)例化的步驟延遲到 GetSingleton() 第一次被調(diào)用時(shí)。
不過(guò)通過(guò) instance == nil 的判斷來(lái)實(shí)現(xiàn)單例并不十分可靠,如果有多個(gè) goroutine 同時(shí)調(diào)用 GetSingleton() 就無(wú)法保證并發(fā)安全。
Go 的內(nèi)建 map 是不支持并發(fā)寫操作的,原因是 map 寫操作不是并發(fā)安全的,當(dāng)你嘗試多個(gè) Goroutine 操作同一個(gè) map,會(huì)產(chǎn)生報(bào)錯(cuò):fatal error: concurrent map writes。
因此官方另外引入了 sync.Map 來(lái)滿足并發(fā)編程中的應(yīng)用。
sync.Map 的實(shí)現(xiàn)原理可概括為:
type Map struct { // 加鎖作用,保護(hù) dirty 字段 mu Mutex // 只讀的數(shù)據(jù),實(shí)際數(shù)據(jù)類型為 readOnly read atomic.Value // 最新寫入的數(shù)據(jù) dirty map[interface{}]*entry // 計(jì)數(shù)器,每次需要讀 dirty 則 +1 misses int}
其中 readOnly 的數(shù)據(jù)結(jié)構(gòu)為:
type readOnly struct { // 內(nèi)建 map m map[interface{}]*entry // 表示 dirty 里存在 read 里沒(méi)有的 key,通過(guò)該字段決定是否加鎖讀 dirty amended bool}
entry 數(shù)據(jù)結(jié)構(gòu)則用于存儲(chǔ)值的指針:
type entry struct { p unsafe.Pointer // 等同于 *interface{}}
屬性 p 有三種狀態(tài):
Map 常用的有以下方法:
redis的基本數(shù)據(jù)結(jié)構(gòu)有: 1、String(字符串);2、Hash(哈希);3、List(列表);4、Set(集合);5、zset(有序集合)。
String 類型是 Redis 中最基本、最常用的數(shù)據(jù)類型,甚至被很多用戶當(dāng)成 Redis 少數(shù)的數(shù)據(jù)類型去使用。String 類型在 Redis 中是二進(jìn)制安全(binary safe)的,這意味著 String 值關(guān)心二進(jìn)制的字符串,不關(guān)心具體格式,你可以用它存儲(chǔ) json 格式或 JPEG 圖片格式的字符串。
應(yīng)用:
Hash的數(shù)據(jù)結(jié)構(gòu)我們可以簡(jiǎn)單理解為java中的 Map,這種結(jié)構(gòu)就特別適合存儲(chǔ)對(duì)象,上面的String的類型確實(shí)也可以存儲(chǔ)對(duì)象,但每次修改對(duì)象中的某一個(gè)屬性,都要拿出整個(gè)json字符串在修改這個(gè)屬性,之后在重新插入,而hash的接口特點(diǎn)讓我們可以只修改該對(duì)象的某一個(gè)屬性。
hash數(shù)據(jù)類型在存儲(chǔ)上述類型的數(shù)據(jù)時(shí)具有比 String 類型更靈活、更快的優(yōu)勢(shì),具體的說(shuō),使用 String 類型存儲(chǔ),必然需要轉(zhuǎn)換和解析 json 格式的字符串,即便不需要轉(zhuǎn)換,在內(nèi)存開(kāi)銷方面,還是 hash 占優(yōu)勢(shì)。
應(yīng)用:
List類型是按照插入順序排序的字符串鏈表,一個(gè)列表非常多可以存儲(chǔ)2^32-1個(gè)元素。我們可以簡(jiǎn)單理解為就相當(dāng)于java中的LinkesdList。和數(shù)據(jù)結(jié)構(gòu)中的普通鏈表一樣,我們可以在其頭部(left)和尾部(right)添加新的元素。在插入時(shí),如果該鍵并不存在,Redis將為該鍵創(chuàng)建一個(gè)新的鏈表。與此相反,如果鏈表中所有的元素均被移除,那么該鍵也將會(huì)被從數(shù)據(jù)庫(kù)中刪除。
應(yīng)用:
Redis 中的 set和Java中的HashSet 有些類似,它內(nèi)部的鍵值對(duì)是無(wú)序的、少數(shù)的。它的內(nèi)部實(shí)現(xiàn)相當(dāng)于一個(gè)特殊的字典,字典中所有的value都是一個(gè)值 NULL。當(dāng)集合中最后一個(gè)元素被移除之后,數(shù)據(jù)結(jié)構(gòu)被自動(dòng)刪除,內(nèi)存被回收。
應(yīng)用:
Sorted-Sets中的每一個(gè)成員都會(huì)有一個(gè)分?jǐn)?shù)(score)與之關(guān)聯(lián),Redis正是通過(guò)分?jǐn)?shù)來(lái)為集合中的成員進(jìn)行從小到大的排序。成員是少數(shù)的,但是分?jǐn)?shù)(score)卻是可以重復(fù)的。
應(yīng)用: 作為有序的,不可重復(fù)的列表,可以做一些排行榜相關(guān)的場(chǎng)景:
當(dāng)大量緩存數(shù)據(jù)在同一時(shí)間過(guò)期(失效)或者 Redis 故障宕機(jī)時(shí),如果此時(shí)有大量的用戶請(qǐng)求,都無(wú)法在 Redis 中處理,于是全部請(qǐng)求都直接訪問(wèn)數(shù)據(jù)庫(kù),從而導(dǎo)致數(shù)據(jù)庫(kù)的壓力驟增,嚴(yán)重的會(huì)造成數(shù)據(jù)庫(kù)宕機(jī),從而形成一系列連鎖反應(yīng),造成整個(gè)系統(tǒng)崩潰,這就是緩存雪崩
我們的業(yè)務(wù)通常會(huì)有幾個(gè)數(shù)據(jù)會(huì)被頻繁地訪問(wèn),比如秒殺活動(dòng),這類被頻地訪問(wèn)的數(shù)據(jù)被稱為熱點(diǎn)數(shù)據(jù)。
如果緩存中的某個(gè)熱點(diǎn)數(shù)據(jù)過(guò)期了,此時(shí)大量的請(qǐng)求訪問(wèn)了該熱點(diǎn)數(shù)據(jù),就無(wú)法從緩存中讀取,直接訪問(wèn)數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)很容易就被高并發(fā)的請(qǐng)求沖垮,這就是緩存擊穿。
當(dāng)發(fā)生緩存雪崩或擊穿時(shí),數(shù)據(jù)庫(kù)中還是保存了應(yīng)用要訪問(wèn)的數(shù)據(jù),一旦緩存恢復(fù)相對(duì)應(yīng)的數(shù)據(jù),就可以減輕數(shù)據(jù)庫(kù)的壓力,而緩存穿透就不一樣了。
當(dāng)用戶訪問(wèn)的數(shù)據(jù),既不在緩存中,也不在數(shù)據(jù)庫(kù)中,導(dǎo)致請(qǐng)求在訪問(wèn)緩存時(shí),發(fā)現(xiàn)緩存缺失,再去訪問(wèn)數(shù)據(jù)庫(kù)時(shí),發(fā)現(xiàn)數(shù)據(jù)庫(kù)中也沒(méi)有要訪問(wèn)的數(shù)據(jù),沒(méi)辦法構(gòu)建緩存數(shù)據(jù),來(lái)服務(wù)后續(xù)的請(qǐng)求。那么當(dāng)有大量這樣的請(qǐng)求到來(lái)時(shí),數(shù)據(jù)庫(kù)的壓力驟增,這就是緩存穿透的問(wèn)題。
約束主要有:主鍵約束、外鍵約束、非空約束、檢査約束(bentwen and ,大于、小于、等于、不等于)、唯一約束。
B+樹(shù)是多叉樹(shù)結(jié)構(gòu),每個(gè)結(jié)點(diǎn)都是一個(gè)16k的數(shù)據(jù)頁(yè),能存放較多索引信息,所以扇出很高。三層左右就可以存儲(chǔ)2kw左右的數(shù)據(jù)(知道結(jié)論就行,想知道原因可以看之前的文章)。也就是說(shuō)查詢一次數(shù)據(jù),如果這些數(shù)據(jù)頁(yè)都在磁盤里,那么最多需要查詢?nèi)未疟PIO。
跳表是鏈表結(jié)構(gòu),一條數(shù)據(jù)一個(gè)結(jié)點(diǎn),如果最底層要存放2kw數(shù)據(jù),且每次查詢都要能達(dá)到二分查找的效果,2kw大概在2的24次方左右,所以,跳表大概高度在24層左右。最壞情況下,這24層數(shù)據(jù)會(huì)分散在不同的數(shù)據(jù)頁(yè)里,也即是查一次數(shù)據(jù)會(huì)經(jīng)歷24次磁盤IO。
因此存放同樣量級(jí)的數(shù)據(jù),B+樹(shù)的高度比跳表的要少,如果放在mysql數(shù)據(jù)庫(kù)上來(lái)說(shuō),就是磁盤IO次數(shù)更少,因此B+樹(shù)查詢更快。
而針對(duì)寫操作,B+樹(shù)需要拆分合并索引數(shù)據(jù)頁(yè),跳表則獨(dú)立插入,并根據(jù)隨機(jī)函數(shù)確定層數(shù),沒(méi)有旋轉(zhuǎn)和維持平衡的開(kāi)銷,因此跳表的寫入性能會(huì)比B+樹(shù)要好。
HTTP2.0(Hypenext TransferProtocol version2)是超文本傳輸協(xié)議的第二版,HTTP2.0相比于HTTP1x,大幅度的提升了web性能,同時(shí)向下兼容HTTP1.X協(xié)議版 本。
主要核心優(yōu)勢(shì)有
1、采用二進(jìn)制格式傳輸數(shù)據(jù),而非htp1.1文本格式,二進(jìn)制格式在協(xié)議的解析和優(yōu)化擴(kuò)展上帶來(lái)了跟多的優(yōu)勢(shì)和可能
2、對(duì)消息頭采用Hpack進(jìn)行壓縮傳輸,能夠節(jié)省消息頭占用的網(wǎng)絡(luò)流量,htp1.1每次請(qǐng)求,都會(huì)攜帶大量冗余的頭信息,浪費(fèi)了很多寬帶資源,
3、異步連接多路復(fù)用
4、Server Push,服務(wù)器端能夠更快的把資源推送到客戶端。
5、保持與HTTP 1.1語(yǔ)義的向后兼容性也是該版本的一個(gè)關(guān)鍵
本文轉(zhuǎn)載自微信公眾號(hào)「王中陽(yáng)Go」,作者「王中陽(yáng)Go」,可以通過(guò)以下二維碼關(guān)注。
轉(zhuǎn)載本文請(qǐng)聯(lián)系「王中陽(yáng)Go」公眾號(hào)。
本文鏈接:http://www.www897cc.com/showinfo-26-98859-0.html阿里校招面試,我來(lái)瞅瞅怎么回事
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com