自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

阿里校招面試,我來瞅瞅怎么回事

開發(fā) 前端
HTTP2.0(Hypenext TransferProtocol version2)是超文本傳輸協(xié)議的第二版,HTTP2.0相比于HTTP1x,大幅度的提升了web性能,同時(shí)向下兼容HTTP1.X協(xié)議版 本。

Go里有哪些數(shù)據(jù)結(jié)構(gòu)是并發(fā)安全的?

并發(fā)安全就是程序在并發(fā)的情況下執(zhí)行的結(jié)果都是正確的;

Go中數(shù)據(jù)類型分為兩大類:

  • 基本數(shù)據(jù)類型:字節(jié)型、整型、布爾型、浮點(diǎn)型、復(fù)數(shù)型、字符串
  • 復(fù)合數(shù)據(jù)類型:數(shù)組、切片、指針、結(jié)構(gòu)體、字典、、函數(shù)、接口

字節(jié)型、布爾型、整型、浮點(diǎn)型取決于操作系統(tǒng)指令值,在64位的指令集架構(gòu)中可以由一條機(jī)器指令完 成,不存在被細(xì)分為更小的操作單位,所以這些類型的并發(fā)賦值是安全的,但是這個(gè)也跟操作系統(tǒng)的位 數(shù)有關(guān),比如int64在32位操作系統(tǒng)中,它的高32位和低32位是分開賦值的,此時(shí)是非并發(fā)安全的。

復(fù)數(shù)類型、字符串、結(jié)構(gòu)體、數(shù)組,切片,字典,通道,接口, 這些底層都是struct,不同成員的賦值 都不是一起的,所以都不是并發(fā)安全的。

Go如何實(shí)現(xiàn)一個(gè)單例模式?

單例模式的作用是確保無論對象被實(shí)例化多少次,全局都只有一個(gè)實(shí)例存在。根據(jù)這一特性,我們可以將其應(yīng)用到全局唯一性配置、數(shù)據(jù)庫連接對象、文件訪問對象等。

餓漢式

餓漢式實(shí)現(xiàn)單例模式非常簡單,直接看代碼:

package singleton
type singleton struct{}
var instance = &singleton{}
func GetSingleton() *singleton {
    return instance
}

singleton 包在被導(dǎo)入時(shí)會(huì)自動(dòng)初始化 instance 實(shí)例,使用時(shí)通過調(diào)用 singleton.GetSingleton() 函數(shù)即可獲得 singleton 這個(gè)結(jié)構(gòu)體的單例對象。

這種方式的單例對象是在包加載時(shí)立即被創(chuàng)建,所以這個(gè)方式叫作餓漢式。與之對應(yīng)的另一種實(shí)現(xiàn)方式叫作懶漢式,懶漢式模式下實(shí)例會(huì)在第一次被使用時(shí)被創(chuàng)建。

需要注意的是,盡管餓漢式實(shí)現(xiàn)單例模式的方式簡單,但大多數(shù)情況下并不推薦。因?yàn)槿绻麊卫龑?shí)例化時(shí)初始化內(nèi)容過多,會(huì)造成程序加載用時(shí)較長。

懶漢式

接下來我們再來看下如何通過懶漢式實(shí)現(xiàn)單例模式:

package singleton
type singleton struct{}
var instance *singleton
func GetSingleton() *singleton {
    if instance == nil {
        instance = &singleton{}
    }
    return instance
}

相較于餓漢式的實(shí)現(xiàn),懶漢式將實(shí)例化 singleton 結(jié)構(gòu)體部分的代碼移到了 GetSingleton() 函數(shù)內(nèi)部。這樣能夠?qū)ο髮?shí)例化的步驟延遲到 GetSingleton() 第一次被調(diào)用時(shí)。

不過通過 instance == nil 的判斷來實(shí)現(xiàn)單例并不十分可靠,如果有多個(gè) goroutine 同時(shí)調(diào)用 GetSingleton() 就無法保證并發(fā)安全。

  1. sync.map的底層實(shí)現(xiàn)
什么是sync.Map

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 來滿足并發(fā)編程中的應(yīng)用。

sync.Map 的實(shí)現(xiàn)原理可概括為:

  • 通過 read 和 dirty 兩個(gè)字段將讀寫分離,讀的數(shù)據(jù)存在只讀字段 read 上,將最新寫入的數(shù)據(jù)則存在 dirty 字段上
  • 讀取時(shí)會(huì)先查詢 read,不存在再查詢 dirty,寫入時(shí)則只寫入 dirty
  • 讀取 read 并不需要加鎖,而讀或?qū)?dirty 都需要加鎖
  • 另外有 misses 字段來統(tǒng)計(jì) read 被穿透的次數(shù)(被穿透指需要讀 dirty 的情況),超過一定次數(shù)則將 dirty 數(shù)據(jù)同步到 read 上
  • 對于刪除數(shù)據(jù)則直接通過標(biāo)記來延遲刪除
數(shù)據(jù)結(jié)構(gòu)
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 里沒有的 key,通過該字段決定是否加鎖讀 dirty
    amended bool
}

entry 數(shù)據(jù)結(jié)構(gòu)則用于存儲(chǔ)值的指針:

type entry struct {
    p unsafe.Pointer  // 等同于 *interface{}
}

屬性 p 有三種狀態(tài):

  • p == nil: 鍵值已經(jīng)被刪除,且 m.dirty == nil
  • p == expunged: 鍵值已經(jīng)被刪除,但 m.dirty!=nil 且 m.dirty 不存在該鍵值(expunged 實(shí)際是空接口指針)
  • 除以上情況,則鍵值對存在,存在于 m.read.m 中,如果 m.dirty!=nil 則也存在于 m.dirty

Map 常用的有以下方法:

  • Load:讀取指定 key 返回 value
  • Store:存儲(chǔ)(增或改)key-value
  • Delete:刪除指定 key

channel在什么情況下會(huì)panic?

  • 關(guān)閉為nil的channel
  • 關(guān)閉一個(gè)已經(jīng)關(guān)閉的通道
  • 向一個(gè)已經(jīng)關(guān)閉的通道寫數(shù)據(jù)
  • 關(guān)閉通道導(dǎo)致發(fā)送阻塞的協(xié)程panic

redis有哪些數(shù)據(jù)結(jié)構(gòu),分別常用于哪些場合?

redis的基本數(shù)據(jù)結(jié)構(gòu)有: 1、String(字符串);2、Hash(哈希);3、List(列表);4、Set(集合);5、zset(有序集合)。

String(字符串)

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)用:

  • 存儲(chǔ)一些配置數(shù)據(jù):在前后分離式開發(fā)中,有些數(shù)據(jù)雖然存儲(chǔ)在數(shù)據(jù)庫,但是更改特別少。比如有個(gè)全國地區(qū)表。當(dāng)前端發(fā)起請求后,后臺(tái)如果每次都從關(guān)系型數(shù)據(jù)庫讀取,會(huì)影響網(wǎng)站整體性能。我們可以在名列前茅次訪問的時(shí)候,將所有地區(qū)信息存儲(chǔ)到redis字符串中,再次請求,直接從數(shù)據(jù)庫中讀取地區(qū)的json字符串,返回給前端。
  • 緩存對象:將對象轉(zhuǎn)為json存儲(chǔ),比如商品信息,用戶信息。
  • 數(shù)據(jù)統(tǒng)計(jì):redis整型可以用來記錄網(wǎng)站訪問量,某個(gè)文件的下載量,簽到人數(shù)、視頻訪問量等等。(自增自減)
  • 時(shí)間內(nèi)限制請求次數(shù):比如已登錄用戶請求短信驗(yàn)證碼,驗(yàn)證碼在5分鐘內(nèi)有效的場景。當(dāng)用戶首次請求了短信接口,將用戶id存儲(chǔ)到redis 已經(jīng)發(fā)送短信的字符串中,并且設(shè)置過期時(shí)間為5分鐘。當(dāng)該用戶再次請求短信接口,發(fā)現(xiàn)已經(jīng)存在該用戶發(fā)送短信記錄,則不再發(fā)送短信。
  • 訂單號(hào)(全局少數(shù)):有時(shí)候你需要去生成一個(gè)全局少數(shù)值的時(shí)候可以通過redis生成。關(guān)鍵命令:incrby(原子自增)。
  • 分布式session:當(dāng)我們用nginx做負(fù)載均衡的時(shí)候,如果我們每個(gè)從服務(wù)器上都各自存儲(chǔ)自己的session,那么當(dāng)切換了服務(wù)器后,session信息會(huì)由于不共享而會(huì)丟失,我們不得不考慮第三應(yīng)用來存儲(chǔ)session。
Hash(哈希)

Hash的數(shù)據(jù)結(jié)構(gòu)我們可以簡單理解為java中的 Map,這種結(jié)構(gòu)就特別適合存儲(chǔ)對象,上面的String的類型確實(shí)也可以存儲(chǔ)對象,但每次修改對象中的某一個(gè)屬性,都要拿出整個(gè)json字符串在修改這個(gè)屬性,之后在重新插入,而hash的接口特點(diǎn)讓我們可以只修改該對象的某一個(gè)屬性。

hash數(shù)據(jù)類型在存儲(chǔ)上述類型的數(shù)據(jù)時(shí)具有比 String 類型更靈活、更快的優(yōu)勢,具體的說,使用 String 類型存儲(chǔ),必然需要轉(zhuǎn)換和解析 json 格式的字符串,即便不需要轉(zhuǎn)換,在內(nèi)存開銷方面,還是 hash 占優(yōu)勢。

應(yīng)用:

  • Redisson分布式鎖:Redisson在實(shí)現(xiàn)分布式鎖的時(shí)候,內(nèi)部的用的數(shù)據(jù)就是hash而不是String。因?yàn)镽edisson為了實(shí)現(xiàn)可重入加鎖機(jī)制。所以在hash中存入了當(dāng)前線程ID。
  • 購物車列表:以用戶id為key,商品id為field,商品數(shù)量為value,恰好構(gòu)成了購物車的3個(gè)要素。
  • 緩存對象:hash類型的 (key, field, value) 的結(jié)構(gòu)與對象的(對象id, 屬性, 值)的結(jié)構(gòu)相似,也可以用來存儲(chǔ)對象。
List(列表)

List類型是按照插入順序排序的字符串鏈表,一個(gè)列表非常多可以存儲(chǔ)2^32-1個(gè)元素。我們可以簡單理解為就相當(dāng)于java中的LinkesdList。和數(shù)據(jù)結(jié)構(gòu)中的普通鏈表一樣,我們可以在其頭部(left)和尾部(right)添加新的元素。在插入時(shí),如果該鍵并不存在,Redis將為該鍵創(chuàng)建一個(gè)新的鏈表。與此相反,如果鏈表中所有的元素均被移除,那么該鍵也將會(huì)被從數(shù)據(jù)庫中刪除。

應(yīng)用:

  • 消息隊(duì)列:lpop和rpush(或者反過來,lpush和rpop)能實(shí)現(xiàn)隊(duì)列的功能。
Set(集合)

Redis 中的 set和Java中的HashSet 有些類似,它內(nèi)部的鍵值對是無序的、少數(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)用:

  • 抽獎(jiǎng)活動(dòng):存儲(chǔ)某活動(dòng)中中獎(jiǎng)的用戶ID ,因?yàn)橛腥ブ毓δ?,可以保證同一個(gè)用戶不會(huì)中獎(jiǎng)兩次。
zset(有序集合)

Sorted-Sets中的每一個(gè)成員都會(huì)有一個(gè)分?jǐn)?shù)(score)與之關(guān)聯(lián),Redis正是通過分?jǐn)?shù)來為集合中的成員進(jìn)行從小到大的排序。成員是少數(shù)的,但是分?jǐn)?shù)(score)卻是可以重復(fù)的。

應(yīng)用: 作為有序的,不可重復(fù)的列表,可以做一些排行榜相關(guān)的場景:

  • 排行榜(商品銷量,視頻評分,用戶游戲分?jǐn)?shù))
  • 新聞熱搜

說下緩存擊穿,緩存穿透,緩存雪崩有什么區(qū)別?

緩存擊穿

當(dāng)大量緩存數(shù)據(jù)在同一時(shí)間過期(失效)或者 Redis 故障宕機(jī)時(shí),如果此時(shí)有大量的用戶請求,都無法在 Redis 中處理,于是全部請求都直接訪問數(shù)據(jù)庫,從而導(dǎo)致數(shù)據(jù)庫的壓力驟增,嚴(yán)重的會(huì)造成數(shù)據(jù)庫宕機(jī),從而形成一系列連鎖反應(yīng),造成整個(gè)系統(tǒng)崩潰,這就是緩存雪崩

緩存擊穿

我們的業(yè)務(wù)通常會(huì)有幾個(gè)數(shù)據(jù)會(huì)被頻繁地訪問,比如秒殺活動(dòng),這類被頻地訪問的數(shù)據(jù)被稱為熱點(diǎn)數(shù)據(jù)。

如果緩存中的某個(gè)熱點(diǎn)數(shù)據(jù)過期了,此時(shí)大量的請求訪問了該熱點(diǎn)數(shù)據(jù),就無法從緩存中讀取,直接訪問數(shù)據(jù)庫,數(shù)據(jù)庫很容易就被高并發(fā)的請求沖垮,這就是緩存擊穿。

緩存穿透

當(dāng)發(fā)生緩存雪崩或擊穿時(shí),數(shù)據(jù)庫中還是保存了應(yīng)用要訪問的數(shù)據(jù),一旦緩存恢復(fù)相對應(yīng)的數(shù)據(jù),就可以減輕數(shù)據(jù)庫的壓力,而緩存穿透就不一樣了。

當(dāng)用戶訪問的數(shù)據(jù),既不在緩存中,也不在數(shù)據(jù)庫中,導(dǎo)致請求在訪問緩存時(shí),發(fā)現(xiàn)緩存缺失,再去訪問數(shù)據(jù)庫時(shí),發(fā)現(xiàn)數(shù)據(jù)庫中也沒有要訪問的數(shù)據(jù),沒辦法構(gòu)建緩存數(shù)據(jù),來服務(wù)后續(xù)的請求。那么當(dāng)有大量這樣的請求到來時(shí),數(shù)據(jù)庫的壓力驟增,這就是緩存穿透的問題。

主鍵索引和唯一索引的區(qū)別

  • 主鍵是一種約束,唯一索引是一種索引,兩者在本質(zhì)上是不同的。
  • 主鍵創(chuàng)建后一定包含一個(gè)唯一性索引,唯一性索引并不一定就是主鍵。
  • 唯一性索引列允許空值,而主鍵列不允許為空值。
  • 主鍵可以被其他表引用為外鍵,而唯一索引不能。
  • 一個(gè)表最多只能創(chuàng)建一個(gè)主鍵,但可以創(chuàng)建多個(gè)唯一索引。
  • 主鍵更適合那些不容易更改的唯一標(biāo)識(shí),如自動(dòng)遞增列、身份證號(hào)等。
  • 在RBO模式下,主鍵的執(zhí)行計(jì)劃優(yōu)先級要高于唯一索引。兩者可以提高查詢的速度。

約束主要有:主鍵約束、外鍵約束、非空約束、檢査約束(bentwen and ,大于、小于、等于、不等于)、唯一約束。

索引為什么使用B+樹,而不使用跳表?

B+樹是多叉樹結(jié)構(gòu),每個(gè)結(jié)點(diǎn)都是一個(gè)16k的數(shù)據(jù)頁,能存放較多索引信息,所以扇出很高。三層左右就可以存儲(chǔ)2kw左右的數(shù)據(jù)(知道結(jié)論就行,想知道原因可以看之前的文章)。也就是說查詢一次數(shù)據(jù),如果這些數(shù)據(jù)頁都在磁盤里,那么最多需要查詢?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ù)頁里,也即是查一次數(shù)據(jù)會(huì)經(jīng)歷24次磁盤IO。

因此存放同樣量級的數(shù)據(jù),B+樹的高度比跳表的要少,如果放在mysql數(shù)據(jù)庫上來說,就是磁盤IO次數(shù)更少,因此B+樹查詢更快。

而針對寫操作,B+樹需要拆分合并索引數(shù)據(jù)頁,跳表則獨(dú)立插入,并根據(jù)隨機(jī)函數(shù)確定層數(shù),沒有旋轉(zhuǎn)和維持平衡的開銷,因此跳表的寫入性能會(huì)比B+樹要好。

計(jì)算機(jī)網(wǎng)絡(luò)的多層模型簡要介紹

  • 應(yīng)用層(Application):為用戶的應(yīng)用程序提供網(wǎng)絡(luò)服務(wù)
  • 表示層(Presentation):將信息表示為一定形式和格式的數(shù)據(jù)流
  • 會(huì)話層(Session):負(fù)責(zé)通信主機(jī)之間會(huì)話的建立、管理和拆除,協(xié)調(diào)通信雙方的會(huì)話
  • 傳輸層(Transport):負(fù)責(zé)通信主機(jī)間端到端的連接
  • 網(wǎng)絡(luò)層(Network):負(fù)責(zé)將分組從源機(jī)送到目的機(jī),包括尋址和最優(yōu)路徑選擇等
  • 數(shù)據(jù)鏈路層(Data Link):提供可靠的幀傳遞,實(shí)現(xiàn)差錯(cuò)控制、流控等等
  • 物理層(Physical):提供透明的比特流(01流)傳遞

http2.0相比與http1.1的優(yōu)化

HTTP2.0(Hypenext TransferProtocol version2)是超文本傳輸協(xié)議的第二版,HTTP2.0相比于HTTP1x,大幅度的提升了web性能,同時(shí)向下兼容HTTP1.X協(xié)議版 本。

主要核心優(yōu)勢有

1、采用二進(jìn)制格式傳輸數(shù)據(jù),而非htp1.1文本格式,二進(jìn)制格式在協(xié)議的解析和優(yōu)化擴(kuò)展上帶來了跟多的優(yōu)勢和可能

2、對消息頭采用Hpack進(jìn)行壓縮傳輸,能夠節(jié)省消息頭占用的網(wǎng)絡(luò)流量,htp1.1每次請求,都會(huì)攜帶大量冗余的頭信息,浪費(fèi)了很多寬帶資源,

3、異步連接多路復(fù)用

4、Server Push,服務(wù)器端能夠更快的把資源推送到客戶端。

5、保持與HTTP 1.1語義的向后兼容性也是該版本的一個(gè)關(guān)鍵

本文轉(zhuǎn)載自微信公眾號(hào)「王中陽Go」,作者「王中陽Go」,可以通過以下二維碼關(guān)注。

轉(zhuǎn)載本文請聯(lián)系「王中陽Go」公眾號(hào)。

責(zé)任編輯:武曉燕 來源: 王中陽
相關(guān)推薦

2014-11-17 09:53:16

負(fù)載均衡

2022-05-09 10:50:13

觀察者模式設(shè)計(jì)模式

2015-07-13 09:45:32

阿里校招

2011-09-13 09:32:28

verizon云安全混合云

2023-03-29 08:24:30

2021-06-04 11:10:04

JavaScript開發(fā)代碼

2019-07-23 17:00:43

HR程序員面試

2010-03-31 17:13:39

筆記本采購

2020-07-03 07:39:45

查詢語句

2020-02-18 11:19:36

物聯(lián)網(wǎng)病毒物聯(lián)網(wǎng)IOT

2024-04-30 10:40:11

2016-11-22 19:54:56

點(diǎn)擊率預(yù)估推薦算法廣告

2023-10-12 08:54:20

Spring事務(wù)設(shè)置

2019-04-19 12:46:18

面試丁校招簡歷

2024-01-08 08:35:28

閉包陷阱ReactHooks

2010-04-20 09:55:37

2021-05-11 11:51:15

飛機(jī)Wi-Fi通信

2013-04-18 09:56:05

2023-03-05 15:41:58

MySQL日志暴漲

2021-07-30 07:28:16

偽類偽元素CSS
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)