Hello,Redis!我們相處已經(jīng)很多年了,從模糊的認(rèn)識到現(xiàn)在我們已經(jīng)深入結(jié)合,你的好我一直都知道也一直都記住,能否再讓我多問你的幾個問題,讓我更加深入的去了解你。 Redis 的通訊協(xié)議是什么 Redis 的通訊協(xié)議是文本協(xié)議,是的,Redis 服務(wù)器與客戶端通過 RESP(Redis Serialization Protocol)協(xié)議通信。 沒錯,文本協(xié)議確實是會浪費流量,不過它的優(yōu)點在于直觀,非常的簡單,解析性能極其的好,我們不需要一個特殊的 Redis 客戶端僅靠 Telnet 或者是文本流就可以跟 Redis 進(jìn)行通訊。 客戶端的命令格式:
簡單總結(jié):具體可以見 https:///topics/protocol ,Redis 文檔認(rèn)為簡單的實現(xiàn),快速的解析,直觀理解是采用 RESP 文本協(xié)議最重要的地方,有可能文本協(xié)議會造成一定量的流量浪費,但卻在性能上和操作上快速簡單,這中間也是一個權(quán)衡和協(xié)調(diào)的過程。Redis 究竟有沒有 ACID 事務(wù) 要弄清楚 Redis 有沒有事務(wù),其實很簡單,上 Rredis 的官網(wǎng)查看文檔,發(fā)現(xiàn): Redis 確實是有事務(wù),不過按照傳統(tǒng)的事務(wù)定義 ACID 來看,Redis 是不是都具備了 ACID 的特性。 ACID 指的是:
我們將使用以上 Redis 事務(wù)的命令來檢驗是否 Redis 都具備了 ACID 的各個特征。 原子性 事務(wù)具備原子性指的是,數(shù)據(jù)庫將事務(wù)中多個操作當(dāng)作一個整體來執(zhí)行,服務(wù)要么執(zhí)行事務(wù)中所有的操作,要么一個操作也不會執(zhí)行。 ①事務(wù)隊列首先弄清楚 Redis 開始事務(wù) multi 命令后,Redis 會為這個事務(wù)生成一個隊列,每次操作的命令都會按照順序插入到這個隊列中。 這個隊列里面的命令不會被馬上執(zhí)行,直到 exec 命令提交事務(wù),所有隊列里面的命令會被一次性,并且排他的進(jìn)行執(zhí)行。 對應(yīng)如下圖: 從上面的例子可以看出,當(dāng)執(zhí)行一個成功的事務(wù),事務(wù)里面的命令都是按照隊列里面順序的并且排他的執(zhí)行。 但原子性又一個特點就是要么全部成功,要么全部失敗,也就是我們傳統(tǒng) DB 里面說的回滾。 當(dāng)我們執(zhí)行一個失敗的事務(wù): 可以發(fā)現(xiàn),就算中間出現(xiàn)了失敗,set abc x 這個操作也已經(jīng)被執(zhí)行了,并沒有進(jìn)行回滾,從嚴(yán)格的意義上來說 Redis 并不具備原子性。 ②為何 Redis 不支持回滾這個其實跟 Redis 的定位和設(shè)計有關(guān)系,先看看為何我們的 MySQL 可以支持回滾,這個還是跟寫 Log 有關(guān)系,Redis 是完成操作之后才會進(jìn)行 AOF 日志記錄,AOF 日志的定位只是記錄操作的指令記錄。 而 MySQL 有完善的 Redolog,并且是在事務(wù)進(jìn)行 Commit 之前就會寫完成 Redolog,Binlog: 要知道 MySQL 為了能進(jìn)行回滾是花了不少的代價,Redis 應(yīng)用的場景更多是對抗高并發(fā)具備高性能,所以 Redis 選擇更簡單,更快速無回滾的方式處理事務(wù)也是符合場景。 一致性 事務(wù)具備一致性指的是,如果數(shù)據(jù)庫在執(zhí)行事務(wù)之前是一致的,那么在事務(wù)執(zhí)行之后,無論事務(wù)是否成功,數(shù)據(jù)庫也應(yīng)該是一致的。 從 Redis 來說可以從 2 個層面看,一個是執(zhí)行錯誤是否有確保一致性,另一個是宕機(jī)時,Redis 是否有確保一致性的機(jī)制。 ①執(zhí)行錯誤是否有確保一致性依然去執(zhí)行一個錯誤的事務(wù),在事務(wù)執(zhí)行的過程中會識別出來并進(jìn)行錯誤處理,這些錯誤并不會對數(shù)據(jù)庫作出修改,也不會對事務(wù)的一致性產(chǎn)生影響。 ②宕機(jī)對一致性的影響暫不考慮分布式高可用的 Redis 解決方案,先從單機(jī)看宕機(jī)恢復(fù)是否能滿意數(shù)據(jù)完整性約束。 無論是 RDB 還是 AOF 持久化方案,可以使用 RDB 文件或 AOF 文件進(jìn)行恢復(fù)數(shù)據(jù),從而將數(shù)據(jù)庫還原到一個一致的狀態(tài)。 ③再議一致性上面執(zhí)行錯誤和宕機(jī)對一致性的影響的觀點摘自黃健宏 《Redis 設(shè)計與實現(xiàn)》。 當(dāng)在讀這章的時候還是有一些存疑的點,歸根到底 Redis 并非關(guān)系型數(shù)據(jù)庫。 如果僅僅就 ACID 的表述上來說,一致性就是從 A 狀態(tài)經(jīng)過事務(wù)到達(dá) B 狀態(tài)沒有破壞各種約束性,僅就 Redis 而言不談實現(xiàn)的業(yè)務(wù),那顯然就是滿意一致性。 但如果加上業(yè)務(wù)去談一致性,例如,A 轉(zhuǎn)賬給 B,A 減少 10 塊錢,B 增加 10 塊錢,因為 Redis 并不具備回滾,也就不具備傳統(tǒng)意義上的原子性,所以 Redis 也應(yīng)該不具備傳統(tǒng)的一致性。 其實,這里只是簡單討論下 Redis 在傳統(tǒng) ACID 上的概念怎么進(jìn)行對接,或許,有可能是我想多了,用傳統(tǒng)關(guān)系型數(shù)據(jù)庫的 ACID 去審核 Redis 是沒有意義的,Redis 本來就沒有意愿去實現(xiàn) ACID 的事務(wù)。 隔離性 隔離性指的是,數(shù)據(jù)庫中有多個事務(wù)并發(fā)的執(zhí)行,各個事務(wù)之間不會相互影響,并且在并發(fā)狀態(tài)下執(zhí)行的事務(wù)和串行執(zhí)行的事務(wù)產(chǎn)生的結(jié)果是完全相同的。 Redis 因為是單線程操作,所以在隔離性上有天生的隔離機(jī)制,當(dāng) Redis 執(zhí)行事務(wù)時,Redis 的服務(wù)端保證在執(zhí)行事務(wù)期間不會對事務(wù)進(jìn)行中斷,所以,Redis 事務(wù)總是以串行的方式運行,事務(wù)也具備隔離性。 持久性 事務(wù)的持久性指的是,當(dāng)一個事務(wù)執(zhí)行完畢,執(zhí)行這個事務(wù)所得到的結(jié)果被保存在持久化的存儲中,即使服務(wù)器在事務(wù)執(zhí)行完成后停機(jī)了,執(zhí)行的事務(wù)的結(jié)果也不會被丟失。 Redis 是否具備持久化,這個取決于 Redis 的持久化模式:
簡單總結(jié):
Redis 和 ACID 純屬站在使用者的角度去思想,Redis 設(shè)計更多的是追求簡單與高性能,不會受制于傳統(tǒng) ACID 的束縛。 Redis 的樂觀鎖 Watch 是怎么實現(xiàn)的 當(dāng)我們一提到樂觀鎖就會想起 CAS(Compare And Set),CAS 操作包含三個操作數(shù):
如果內(nèi)存位置的值與預(yù)期原值相匹配,那么處理器會自動將該位置更新為新值。否則,處理器不做任何操作。 在 Redis 的事務(wù)中使用 Watch 實現(xiàn),Watch 會在事務(wù)開始之前盯住 1 個或多個關(guān)鍵變量。 當(dāng)事務(wù)執(zhí)行時,也就是服務(wù)器收到了 exec 指令要順序執(zhí)行緩存的事務(wù)隊列時, Redis 會檢查關(guān)鍵變量自 Watch 之后,是否被修改了。 ①Java 的 AtomicXXX 的樂觀鎖機(jī)制在 Java 中我們也經(jīng)常的使用到一些樂觀鎖的參數(shù),例如 AtomicXXX,這些機(jī)制的背后是怎么去實現(xiàn)的,是否 Redis 也跟 Java 的 CAS 實現(xiàn)機(jī)制一樣? 先來看看 Java 的 Atomic 類,我們追一下源碼,可以看到它的背后其實是 Unsafe_CompareAndSwapObject: 可以看見 compareAndSwapObject 是 Native 方法,需要在繼續(xù)追查,可以下載源碼或打開 :http://hg.openjdk./jdk8u/。 ②Cmpxchg可以發(fā)現(xiàn)追查到最終 CAS,“比較并修改”,本來是兩個語意,但是最終確實一條 CPU 指令 Cmpxchg 完成。 Cmpxchg 是一條 CPU 指令的命令而不是多條 CPU 指令,所以它不會被多線程的調(diào)度所打斷,所以能夠保證 CAS 的操作是一個原子操作。 當(dāng)然 Cmpxchg 的機(jī)制其實存在 ABA 還有多次重試的問題,這個不在這里討論。 ③Redis 的 Watch 機(jī)制Redis 的 Watch 也是使用 Cmpxchg 嗎,兩者存在相似之處在用法上也有一些不同,Redis 的 Watch 不存在 ABA 問題,也沒有多次重試機(jī)制,其中有一個重大的不同是:Redis 事務(wù)執(zhí)行其實是串行的。 簡單追一下源碼:摘錄出來的源碼可能有些凌亂,不過可以簡單總結(jié)出來數(shù)據(jù)結(jié)構(gòu)圖和簡單的流程圖,之后再看源碼就會清晰很多。 存儲如下圖: RedisDb 存放了一個 watched_keys 的 Dcit 結(jié)構(gòu),每個被 Watch 的 Key 的值是一個鏈表結(jié)構(gòu),存放的是一組 Redis 客戶端標(biāo)志。 流程如下圖: 每一次 Watch,Multi,Exec 時都會去查詢這個 watched_keys 結(jié)構(gòu)進(jìn)行判斷,每次 Touch 到被 Watch 的 Key 時都會標(biāo)志為 CLIENT_DIRTY_CAS。 因為在 Redis 中所有的事務(wù)都是串行的,假設(shè)有客戶端 A 和客戶端 B 都 Watch 同一個 Key。 當(dāng)客戶端 A 進(jìn)行 Touch 修改或者 A 率先執(zhí)行完,會把客戶端 A 從這個 watched_keys 的這個 Key 的列表刪除,然后把這個列表所有的客戶端都設(shè)置成 CLIENT_DIRTY_CAS。 當(dāng)后面的客戶端 B 開始執(zhí)行時,判斷到自己的狀態(tài)是 CLIENT_DIRTY_CAS,便 discardTransaction 終止事務(wù)。 簡單總結(jié):Cmpxchg 的實現(xiàn)主要是利用了 CPU 指令,看似兩個操作使用一條 CPU 指令完成,所以不會被多線程進(jìn)行打斷。而 Redis 的 Watch 機(jī)制,更多是利用了 Redis 本身單線程的機(jī)制,采用了 watched_keys 的數(shù)據(jù)結(jié)構(gòu)和串行流程實現(xiàn)了樂觀鎖機(jī)制。 Redis 是如何持久化的 Redis 的持久化有兩種機(jī)制,一個是 RDB,也就是快照,快照就是一次全量的備份,會把所有 Redis 的內(nèi)存數(shù)據(jù)進(jìn)行二進(jìn)制的序列化存儲到磁盤。 另一種是 AOF 日志,AOF 日志記錄的是數(shù)據(jù)操作修改的指令記錄日志,可以類比 MySQL 的 Binlog,AOF 日期隨著時間的推移只會無限增量。 在對 Redis 進(jìn)行恢復(fù)時,RDB 快照直接讀取磁盤即可恢復(fù),而 AOF 需要對所有的操作指令進(jìn)行重放進(jìn)行恢復(fù),這個過程有可能非常漫長。 RDB Redis 在進(jìn)行 RDB 的快照生成有兩種方法,一種是 Save,由于 Redis 是單進(jìn)程單線程,直接使用 Save,Redis 會進(jìn)行一個龐大的文件 IO 操作。 由于單進(jìn)程單線程勢必會阻塞線上的業(yè)務(wù),一般的話不會直接采用 Save,而是采用 Bgsave,之前一直說 Redis 是單進(jìn)程單線程,其實不然。 在使用 Bgsave 的時候,Redis 會 Fork 一個子進(jìn)程,快照的持久化就交給子進(jìn)程去處理,而父進(jìn)程繼續(xù)處理線上業(yè)務(wù)的請求。 ①Fork 機(jī)制 想要弄清楚 RDB 快照的生成原理就必須弄清楚 Fork 機(jī)制,F(xiàn)ork 機(jī)制是 Linux 操作系統(tǒng)的一個進(jìn)程機(jī)制。 當(dāng)父進(jìn)程 Fork 出來一個子進(jìn)程,子進(jìn)程和父進(jìn)程擁有共同的內(nèi)存數(shù)據(jù)結(jié)構(gòu),子進(jìn)程剛剛產(chǎn)生時,它和父進(jìn)程共享內(nèi)存里面的代碼段和數(shù)據(jù)段。 一開始兩個進(jìn)程都具備了相同的內(nèi)存段,子進(jìn)程在做數(shù)據(jù)持久化時,不會去修改現(xiàn)在的內(nèi)存數(shù)據(jù),而是會采用 COW(Copy On Write)的方式將數(shù)據(jù)段頁面進(jìn)行分離。 當(dāng)父進(jìn)程修改了某一個數(shù)據(jù)段時,被共享的頁面就會復(fù)制一份分離出來,然后父進(jìn)程再在新的數(shù)據(jù)段進(jìn)行修改。 ②分裂 這個過程也成為分裂的過程,本來父子進(jìn)程都指向很多相同的內(nèi)存塊,但是如果父進(jìn)程對其中某個內(nèi)存塊進(jìn)行該修改,就會將其復(fù)制出來,進(jìn)行分裂再在新的內(nèi)存塊上面進(jìn)行修改。 因為子進(jìn)程在 Fork 的時候就可以固定內(nèi)存,這個時間點的數(shù)據(jù)將不會產(chǎn)生變化。 所以我們可以安心的產(chǎn)生快照不用擔(dān)心快照的內(nèi)容受到父進(jìn)程業(yè)務(wù)請求的影響。 另外可以想象,如果在 Bgsave 的過程中,Redis 沒有任何操作,父進(jìn)程沒有接收到任何業(yè)務(wù)請求也沒有任何的背后例如過期移除等操作,父進(jìn)程和子進(jìn)程將會使用相同的內(nèi)存塊。 AOF AOF 是 Redis 操作指令的日志存儲,類同于 MySQL 的 Binlog,假設(shè) AOF 從 Redis 創(chuàng)建以來就一直執(zhí)行,那么 AOF 就記錄了所有的 Redis 指令的記錄。 如果要恢復(fù) Redis,可以對 AOF 進(jìn)行指令重放,便可修復(fù)整個 Redis 實例。 不過 AOF 日志也有兩個比較大的問題:
AOF 寫操作是在 Redis 處理完業(yè)務(wù)邏輯之后,按照一定的策略才會進(jìn)行些 AOF 日志存盤,這點跟 MySQL 的 Redolog 和 Binlog 有很大的不同。 也因為此原因,Redis 因為處理邏輯在前而記錄操作日志在后,也是導(dǎo)致 Redis 無法進(jìn)行回滾的一個原因。 bgrewriteaof:針對上述的問題,Redis 在 2.4 之后也使用了 bgrewriteaof 對 AOF 日志進(jìn)行瘦身。bgrewriteaof 命令用于異步執(zhí)行一個 AOF 文件重寫操作。重寫會創(chuàng)建一個當(dāng)前 AOF 文件的體積優(yōu)化版本。RDB 和 AOF 混合搭配模式 在對 Redis 進(jìn)行恢復(fù)的時候,如果我們采用了 RDB 的方式,因為 Bgsave 的策略,可能會導(dǎo)致我們丟失大量的數(shù)據(jù)。 如果我們采用了 AOF 的模式,通過 AOF 操作日志重放恢復(fù),重放 AOF 日志比 RDB 要長久很多。 Redis 4.0 之后,為了解決這個問題,引入了新的持久化模式,混合持久化,將 RDB 的文件和局部增量的 AOF 文件相結(jié)合。 RDB 可以使用相隔較長的時間保存策略,AOF 不需要是全量日志,只需要保存前一次 RDB 存儲開始到這段時間增量 AOF 日志即可,一般來說,這個日志量是非常小的。 Redis 在內(nèi)存使用上是如何開源節(jié)流 Redis 跟其他傳統(tǒng)數(shù)據(jù)庫不同,Redis 是一個純內(nèi)存的數(shù)據(jù)庫,并且存儲了都是一些數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù),如果不對內(nèi)存加以控制的話,Redis 很可能會因為數(shù)據(jù)量過大導(dǎo)致系統(tǒng)的奔潰。 Ziplist
當(dāng)最開始嘗試開啟一個小數(shù)據(jù)量的 Hash 結(jié)構(gòu)和一個 Zset 結(jié)構(gòu)時,發(fā)現(xiàn)他們在 Redis 里面的真正結(jié)構(gòu)類型是一個 Ziplist。 Ziplist 是一個緊湊的數(shù)據(jù)結(jié)構(gòu),每一個元素之間都是連續(xù)的內(nèi)存,如果在 Redis 中,Redis 啟用的數(shù)據(jù)結(jié)構(gòu)數(shù)據(jù)量很小時,Redis 就會切換到使用緊湊存儲的形式來進(jìn)行壓縮存儲。 例如,上面的例子,我們采用了 Hash 結(jié)構(gòu)進(jìn)行存儲,Hash 結(jié)構(gòu)是一個二維的結(jié)構(gòu),是一個典型的用空間換取時間的結(jié)構(gòu)。 但是如果使用的數(shù)據(jù)量很小,使用二維結(jié)構(gòu)反而浪費了空間,在時間的性能上也并沒有得到太大的提升,還不如直接使用一維結(jié)構(gòu)進(jìn)行存儲。 在查找的時候,雖然復(fù)雜度是 O(n),但是因為數(shù)據(jù)量少遍歷也非??欤鲋帘?Hash 結(jié)構(gòu)本身的查詢更快。 如果當(dāng)集合對象的元素不斷的增加,或者某個 Value 的值過大,這種小對象存儲也會升級生成標(biāo)準(zhǔn)的結(jié)構(gòu)。 Redis 也可以在配置中進(jìn)行定義緊湊結(jié)構(gòu)和標(biāo)準(zhǔn)結(jié)構(gòu)的轉(zhuǎn)換參數(shù):
Quicklist
Quicklist 數(shù)據(jù)結(jié)構(gòu)是 Redis 在 3.2 才引入的一個雙向鏈表的數(shù)據(jù)結(jié)構(gòu),確實來說是一個 Ziplist 的雙向鏈表。 Quicklist 的每一個數(shù)據(jù)節(jié)點是一個 Ziplist,Ziplist 本身就是一個緊湊列表。 假使,Quicklist 包含了 5 個 Ziplist 的節(jié)點,每個 Ziplist 列表又包含了 5 個數(shù)據(jù),那么在外部看來,這個 Quicklist 就包含了 25 個數(shù)據(jù)項。 Quicklist 的結(jié)構(gòu)設(shè)計簡單總結(jié)起來,是一個空間和時間的折中方案:
所以,結(jié)合 Ziplist 和雙向鏈表的優(yōu)點,Quciklist 就孕育而生。 對象共享 Redis 在自己的對象系統(tǒng)中構(gòu)建了一個引用計數(shù)方法,通過這個方法程序可以跟蹤對象的引用計數(shù)信息,除了可以在適當(dāng)?shù)臅r候進(jìn)行對象釋放,還可以用來作為對象共享。 舉個例子,假使鍵 A 創(chuàng)建了一個整數(shù)值 100 的字符串作為值對象,這個時候鍵 B 也創(chuàng)建保存同樣整數(shù)值 100 的字符串對象作為值對象。 那么在 Redis 的操作時:
假使,我們的數(shù)據(jù)庫中指向整數(shù)值 100 的鍵不止鍵 A 和鍵 B,而是有幾百個,那么 Redis 服務(wù)器中只需要一個字符串對象的內(nèi)存就可以保存原本需要幾百個字符串對象的內(nèi)存才能保存的數(shù)據(jù)。 Redis 是如何實現(xiàn)主從復(fù)制 幾個定義:
在 Redis 2.8 之后,使用 Psync 命令代替 Sync 命令來執(zhí)行復(fù)制的同步操作。 Psync 命令具有完整重同步和部分重同步兩種模式:
完整重同步:
如果網(wǎng)絡(luò)的抖動或者是短時間的斷鏈也需要進(jìn)行完整同步就會導(dǎo)致大量的開銷,這些開銷包括了,Bgsave 的時間,RDB 文件傳輸?shù)臅r間,Slave 重新加載 RDB 時間,如果 Slave 有 AOF,還會導(dǎo)致 AOF 重寫。 這些都是大量的開銷,所以在 Redis 2.8 之后也實現(xiàn)了部分重同步的機(jī)制。 部分重同步:
Redis 是怎么制定過期刪除策略的 當(dāng)一個鍵處于過期的狀態(tài),其實在 Redis 中這個內(nèi)存并不是實時就被從內(nèi)存中進(jìn)行摘除,而是 Redis 通過一定的機(jī)制去把一些處于過期鍵進(jìn)行移除,進(jìn)而達(dá)到內(nèi)存的釋放,那么當(dāng)一個鍵處于過期,Redis 會在什么時候去刪除? 幾時被刪除存在三種可能性,這三種可能性也代表了 Redis 的三種不同的刪除策略。
①定時刪除設(shè)置鍵的過期時間,創(chuàng)建定時器,一旦過期時間來臨,就立即對鍵進(jìn)行操作。 這種對內(nèi)存是友好的,但是對 CPU 的時間是最不友好的,特別是在業(yè)務(wù)繁忙,過期鍵很多的時候,刪除過期鍵這個操作就會占據(jù)很大一部分 CPU 的時間。 要知道 Redis 是單線程操作,在內(nèi)存不緊張而 CPU 緊張的時候,將 CPU 的時間浪費在與業(yè)務(wù)無關(guān)的刪除過期鍵上面,會對 Redis 的服務(wù)器的響應(yīng)時間和吞吐量造成影響。 另外,創(chuàng)建一個定時器需要用到 Redis 服務(wù)器中的時間事件,而當(dāng)前時間事件的實現(xiàn)方式是無序鏈表,時間復(fù)雜度為 O(n),讓服務(wù)器大量創(chuàng)建定時器去實現(xiàn)定時刪除策略,會產(chǎn)生較大的性能影響,所以,定時刪除并不是一種好的刪除策略。 ②惰性刪除與定時刪除相反,惰性刪除策略對 CPU 來說是最友好的,程序只有在取出鍵的時候才會進(jìn)行檢查,是一種被動的過程。 與此同時,惰性刪除對內(nèi)存來說又是最不友好的,一個鍵過期,只要不再被取出,這個過期鍵就不會被刪除,它占用的內(nèi)存也不會被釋放。 很明顯,惰性刪除也不是一個很好的策略,Redis 是非常依賴內(nèi)存和較好內(nèi)存的,如果一些長期鍵長期沒有被訪問,就會造成大量的內(nèi)存垃圾,甚至?xí)俪蓛?nèi)存的泄漏。 在對執(zhí)行數(shù)據(jù)寫入時,通過 expireIfNeeded 函數(shù)對寫入的 Key 進(jìn)行過期判斷。 其中 expireIfNeeded 在內(nèi)部做了三件事情,分別是:
③定期刪除上面兩種刪除策略,無論是定時刪除和惰性刪除,這兩種刪除方式在單一的使用上都存在明顯的缺陷,要么占用太多 CPU 時間,要么浪費太多內(nèi)存。 定期刪除策略是前兩種策略的一個整合和折中:
總結(jié) Redis 可謂博大精深,簡單的七連問只是盲人摸象,這次只是摸到了一根象鼻子,還應(yīng)該順著鼻子向下摸,下次可能摸到了一只象耳朵。 只要愿意往下深入去了解去摸索,而不只應(yīng)用不思考,總有一天會把 Redis 這只大象給摸透了。 作者:陳于喆,注:部分章節(jié)參考和引用黃健宏 《Redis 設(shè)計與實現(xiàn)》 簡介:十余年的開發(fā)和架構(gòu)經(jīng)驗,國內(nèi)較早一批微服務(wù)開發(fā)實施者。曾任職國內(nèi)互聯(lián)網(wǎng)公司網(wǎng)易和唯品會高級研發(fā)工程師,后在創(chuàng)業(yè)公司擔(dān)任技術(shù)總監(jiān)/架構(gòu)師,目前在洋蔥集團(tuán)任職技術(shù)研發(fā)副總監(jiān)。負(fù)責(zé)技術(shù)部門研發(fā)體系建設(shè),團(tuán)建建設(shè),人才培養(yǎng),推動整個技術(shù)架構(gòu)演進(jìn)以及升級,帶領(lǐng)技術(shù)團(tuán)隊構(gòu)建微服務(wù)架構(gòu)體系、平臺架構(gòu)體系、自動化運維體系。
|
|
來自: 昵稱10087950 > 《JAVA》