1、引言
IM等社交應(yīng)用的開發(fā)工作中,亂碼問題也很常見,比如:
1)IM聊天消息中的Emoji表情為什么發(fā)給后端后MySQL數(shù)據(jù)庫里會(huì)亂碼;
2)文件名中帶有中文的大文件聊天消息發(fā)送后,對(duì)方看到的文名是亂碼;
3)Http rest接口調(diào)用時(shí),后端讀取到APP端傳過來的參數(shù)有中文亂碼問題;
... ...
那么,對(duì)于亂碼這個(gè)看似不起眼,但并不是一兩話能講清楚的問題,是很有必要從根源了解字符集和編碼原理,知其然知其所以然顯然是一個(gè)優(yōu)秀碼農(nóng)的基本素養(yǎng),所以,便有了本文,希望能幫助到你。
* 推薦閱讀:關(guān)于字符編碼知識(shí)的詳細(xì)講解請(qǐng)見《字符編碼那點(diǎn)事:快速理解ASCII、Unicode、GBK和UTF-8》。
學(xué)習(xí)交流:
- 即時(shí)通訊/推送技術(shù)開發(fā)交流5群:215477170 [推薦]
- 移動(dòng)端IM開發(fā)入門文章:《新手入門一篇就夠:從零開發(fā)移動(dòng)端IM》
(本文同步發(fā)布于:http://www.52im.net/thread-2868-1-1.html)
IM等社交應(yīng)用的開發(fā)工作中,亂碼問題也很常見,比如:
1)IM聊天消息中的Emoji表情為什么發(fā)給后端后MySQL數(shù)據(jù)庫里會(huì)亂碼;
2)文件名中帶有中文的大文件聊天消息發(fā)送后,對(duì)方看到的文名是亂碼;
3)Http rest接口調(diào)用時(shí),后端讀取到APP端傳過來的參數(shù)有中文亂碼問題;
... ...
那么,對(duì)于亂碼這個(gè)看似不起眼,但并不是一兩話能講清楚的問題,是很有必要從根源了解字符集和編碼原理,知其然知其所以然顯然是一個(gè)優(yōu)秀碼農(nóng)的基本素養(yǎng),所以,便有了本文,希望能幫助到你。
* 推薦閱讀:關(guān)于字符編碼知識(shí)的詳細(xì)講解請(qǐng)見《字符編碼那點(diǎn)事:快速理解ASCII、Unicode、GBK和UTF-8》。
學(xué)習(xí)交流:
- 即時(shí)通訊/推送技術(shù)開發(fā)交流5群:215477170 [推薦]
- 移動(dòng)端IM開發(fā)入門文章:《新手入門一篇就夠:從零開發(fā)移動(dòng)端IM》
(本文同步發(fā)布于:http://www.52im.net/thread-2868-1-1.html)
2、關(guān)于作者

盧鈞軼:愛搗騰Linux的DBA。曾任職于大眾點(diǎn)評(píng)網(wǎng)DBA團(tuán)隊(duì),主要關(guān)注MySQL、Memcache、MMM等產(chǎn)品的高性能和高可用架構(gòu)。
個(gè)人微博:米雪兒儂好的cenalulu
Github地址:https://github.com/cenalulu

盧鈞軼:愛搗騰Linux的DBA。曾任職于大眾點(diǎn)評(píng)網(wǎng)DBA團(tuán)隊(duì),主要關(guān)注MySQL、Memcache、MMM等產(chǎn)品的高性能和高可用架構(gòu)。
個(gè)人微博:米雪兒儂好的cenalulu
Github地址:https://github.com/cenalulu
3、系列文章
本文是IM開發(fā)干貨系列文章中的第21篇,總目錄如下:
《IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(一):保證在線實(shí)時(shí)消息的可靠投遞》
《IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(二):保證離線消息的可靠投遞》
《如何保證IM實(shí)時(shí)消息的“時(shí)序性”與“一致性”?》
《IM單聊和群聊中的在線狀態(tài)同步應(yīng)該用“推”還是“拉”?》
《一種Android端IM智能心跳算法的設(shè)計(jì)與實(shí)現(xiàn)探討(含樣例代碼)》
《移動(dòng)端IM登錄時(shí)拉取數(shù)據(jù)如何作到省流量?》
《通俗易懂:基于集群的移動(dòng)端IM接入層負(fù)載均衡方案分享》
《淺談移動(dòng)端IM的多點(diǎn)登陸和消息漫游原理》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(一):正確理解前置HTTP SSO單點(diǎn)登陸接口的原理》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(二):如何設(shè)計(jì)大量圖片文件的服務(wù)端存儲(chǔ)架構(gòu)?》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(三):快速理解服務(wù)端數(shù)據(jù)庫讀寫分離原理及實(shí)踐建議》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(四):正確理解HTTP短連接中的Cookie、Session和Token》
《IM群聊消息的已讀回執(zhí)功能該怎么實(shí)現(xiàn)?》
《IM群聊消息究竟是存1份(即擴(kuò)散讀)還是存多份(即擴(kuò)散寫)?》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(五):通俗易懂,正確理解并用好MQ消息隊(duì)列》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(六):數(shù)據(jù)庫用NoSQL還是SQL?讀這篇就夠了!》
《IM里“附近的人”功能實(shí)現(xiàn)原理是什么?如何高效率地實(shí)現(xiàn)它?》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(七):主流移動(dòng)端賬號(hào)登錄方式的原理及設(shè)計(jì)思路》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(八):史上最通俗,徹底搞懂字符亂碼問題的本質(zhì)》(本文)
本文是IM開發(fā)干貨系列文章中的第21篇,總目錄如下:
《IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(一):保證在線實(shí)時(shí)消息的可靠投遞》
《IM消息送達(dá)保證機(jī)制實(shí)現(xiàn)(二):保證離線消息的可靠投遞》
《如何保證IM實(shí)時(shí)消息的“時(shí)序性”與“一致性”?》
《IM單聊和群聊中的在線狀態(tài)同步應(yīng)該用“推”還是“拉”?》
《一種Android端IM智能心跳算法的設(shè)計(jì)與實(shí)現(xiàn)探討(含樣例代碼)》
《移動(dòng)端IM登錄時(shí)拉取數(shù)據(jù)如何作到省流量?》
《通俗易懂:基于集群的移動(dòng)端IM接入層負(fù)載均衡方案分享》
《淺談移動(dòng)端IM的多點(diǎn)登陸和消息漫游原理》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(一):正確理解前置HTTP SSO單點(diǎn)登陸接口的原理》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(二):如何設(shè)計(jì)大量圖片文件的服務(wù)端存儲(chǔ)架構(gòu)?》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(三):快速理解服務(wù)端數(shù)據(jù)庫讀寫分離原理及實(shí)踐建議》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(四):正確理解HTTP短連接中的Cookie、Session和Token》
《IM群聊消息的已讀回執(zhí)功能該怎么實(shí)現(xiàn)?》
《IM群聊消息究竟是存1份(即擴(kuò)散讀)還是存多份(即擴(kuò)散寫)?》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(五):通俗易懂,正確理解并用好MQ消息隊(duì)列》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(六):數(shù)據(jù)庫用NoSQL還是SQL?讀這篇就夠了!》
《IM里“附近的人”功能實(shí)現(xiàn)原理是什么?如何高效率地實(shí)現(xiàn)它?》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(七):主流移動(dòng)端賬號(hào)登錄方式的原理及設(shè)計(jì)思路》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(八):史上最通俗,徹底搞懂字符亂碼問題的本質(zhì)》(本文)
4、正文概述
字符集和編碼無疑是IT菜鳥甚至是各種大神的頭痛問題。當(dāng)遇到紛繁復(fù)雜的字符集,各種火星文和亂碼時(shí),問題的定位往往變得非常困難。
本文內(nèi)容就將會(huì)從原理方面對(duì)字符集和編碼做個(gè)簡單的科普介紹,同時(shí)也會(huì)介紹一些通用的亂碼故障定位的方法以方便讀者以后能夠更從容的定位相關(guān)問題。
在正式介紹之前,先做個(gè)小申明:如果你希望非常精確的理解各個(gè)名詞的解釋,那么可以詳細(xì)閱讀這篇《字符編碼那點(diǎn)事:快速理解ASCII、Unicode、GBK和UTF-8》。
本文是博主通過自己理解消化后并轉(zhuǎn)化成易懂淺顯的表述后的介紹,會(huì)盡量以簡單明了的文字來從要源講解字符集、字符編碼的概念,以及在遭遇亂碼時(shí)的一些常用診斷技巧,希望能助你對(duì)于“亂碼”問題有更深地理解。
字符集和編碼無疑是IT菜鳥甚至是各種大神的頭痛問題。當(dāng)遇到紛繁復(fù)雜的字符集,各種火星文和亂碼時(shí),問題的定位往往變得非常困難。
本文內(nèi)容就將會(huì)從原理方面對(duì)字符集和編碼做個(gè)簡單的科普介紹,同時(shí)也會(huì)介紹一些通用的亂碼故障定位的方法以方便讀者以后能夠更從容的定位相關(guān)問題。
在正式介紹之前,先做個(gè)小申明:如果你希望非常精確的理解各個(gè)名詞的解釋,那么可以詳細(xì)閱讀這篇《字符編碼那點(diǎn)事:快速理解ASCII、Unicode、GBK和UTF-8》。
本文是博主通過自己理解消化后并轉(zhuǎn)化成易懂淺顯的表述后的介紹,會(huì)盡量以簡單明了的文字來從要源講解字符集、字符編碼的概念,以及在遭遇亂碼時(shí)的一些常用診斷技巧,希望能助你對(duì)于“亂碼”問題有更深地理解。
5、什么是字符集
在介紹字符集之前,我們先了解下為什么要有字符集。
我們?cè)谟?jì)算機(jī)屏幕上看到的是實(shí)體化的文字,而在計(jì)算機(jī)存儲(chǔ)介質(zhì)中存放的實(shí)際是二進(jìn)制的比特流。那么在這兩者之間的轉(zhuǎn)換規(guī)則就需要一個(gè)統(tǒng)一的標(biāo)準(zhǔn),否則把我們的U盤插到老板的電腦上,文檔就亂碼了;小伙伴QQ上傳過來的文件,在我們本地打開又亂碼了。
于是為了實(shí)現(xiàn)轉(zhuǎn)換標(biāo)準(zhǔn),各種字符集標(biāo)準(zhǔn)就出現(xiàn)了。
簡單的說:字符集就規(guī)定了某個(gè)文字對(duì)應(yīng)的二進(jìn)制數(shù)字存放方式(編碼)和某串二進(jìn)制數(shù)值代表了哪個(gè)文字(解碼)的轉(zhuǎn)換關(guān)系。
那么為什么會(huì)有那么多字符集標(biāo)準(zhǔn)呢?
這個(gè)問題實(shí)際非常容易回答。問問自己為什么我們的插頭拿到英國就不能用了呢?為什么顯示器同時(shí)有DVI、VGA、HDMI、DP這么多接口呢?很多規(guī)范和標(biāo)準(zhǔn)在最初制定時(shí)并不會(huì)意識(shí)到這將會(huì)是以后全球普適的準(zhǔn)則,或者處于組織本身利益就想從本質(zhì)上區(qū)別于現(xiàn)有標(biāo)準(zhǔn)。于是,就產(chǎn)生了那么多具有相同效果但又不相互兼容的標(biāo)準(zhǔn)了。
說了那么多我們來看一個(gè)實(shí)際例子,下面就是“屌”這個(gè)字在各種編碼下的十六進(jìn)制和二進(jìn)制編碼結(jié)果,怎么樣有沒有一種很屌的感覺?

在介紹字符集之前,我們先了解下為什么要有字符集。
我們?cè)谟?jì)算機(jī)屏幕上看到的是實(shí)體化的文字,而在計(jì)算機(jī)存儲(chǔ)介質(zhì)中存放的實(shí)際是二進(jìn)制的比特流。那么在這兩者之間的轉(zhuǎn)換規(guī)則就需要一個(gè)統(tǒng)一的標(biāo)準(zhǔn),否則把我們的U盤插到老板的電腦上,文檔就亂碼了;小伙伴QQ上傳過來的文件,在我們本地打開又亂碼了。
于是為了實(shí)現(xiàn)轉(zhuǎn)換標(biāo)準(zhǔn),各種字符集標(biāo)準(zhǔn)就出現(xiàn)了。
簡單的說:字符集就規(guī)定了某個(gè)文字對(duì)應(yīng)的二進(jìn)制數(shù)字存放方式(編碼)和某串二進(jìn)制數(shù)值代表了哪個(gè)文字(解碼)的轉(zhuǎn)換關(guān)系。
那么為什么會(huì)有那么多字符集標(biāo)準(zhǔn)呢?
這個(gè)問題實(shí)際非常容易回答。問問自己為什么我們的插頭拿到英國就不能用了呢?為什么顯示器同時(shí)有DVI、VGA、HDMI、DP這么多接口呢?很多規(guī)范和標(biāo)準(zhǔn)在最初制定時(shí)并不會(huì)意識(shí)到這將會(huì)是以后全球普適的準(zhǔn)則,或者處于組織本身利益就想從本質(zhì)上區(qū)別于現(xiàn)有標(biāo)準(zhǔn)。于是,就產(chǎn)生了那么多具有相同效果但又不相互兼容的標(biāo)準(zhǔn)了。
說了那么多我們來看一個(gè)實(shí)際例子,下面就是“屌”這個(gè)字在各種編碼下的十六進(jìn)制和二進(jìn)制編碼結(jié)果,怎么樣有沒有一種很屌的感覺?

6、什么是字符編碼
字符集只是一個(gè)規(guī)則集合的名字,對(duì)應(yīng)到真實(shí)生活中,字符集就是對(duì)某種語言的稱呼。例如:英語,漢語,日語。
對(duì)于一個(gè)字符集來說要正確編碼轉(zhuǎn)碼一個(gè)字符需要三個(gè)關(guān)鍵元素:
1)字庫表(character repertoire):是一個(gè)相當(dāng)于所有可讀或者可顯示字符的數(shù)據(jù)庫,字庫表決定了整個(gè)字符集能夠展現(xiàn)表示的所有字符的范圍;
2)編碼字符集(coded character set):即用一個(gè)編碼值code point來表示一個(gè)字符在字庫中的位置;
3)字符編碼(character encoding form):將編碼字符集和實(shí)際存儲(chǔ)數(shù)值之間的轉(zhuǎn)換關(guān)系。
一般來說都會(huì)直接將code point的值作為編碼后的值直接存儲(chǔ)。例如在ASCII中“A”在表中排第65位,而編碼后A的數(shù)值是 0100 0001 也即十進(jìn)制的65的二進(jìn)制轉(zhuǎn)換結(jié)果。
看到這里,可能很多讀者都會(huì)有和我當(dāng)初一樣的疑問:字庫表和編碼字符集看來是必不可少的,那既然字庫表中的每一個(gè)字符都有一個(gè)自己的序號(hào),直接把序號(hào)作為存儲(chǔ)內(nèi)容就好了。為什么還要多此一舉通過字符編碼把序號(hào)轉(zhuǎn)換成另外一種存儲(chǔ)格式呢?
其實(shí)原因也比較容易理解:統(tǒng)一字庫表的目的是為了能夠涵蓋世界上所有的字符,但實(shí)際使用過程中會(huì)發(fā)現(xiàn)真正用的上的字符相對(duì)整個(gè)字庫表來說比例非常低。例如中文地區(qū)的程序幾乎不會(huì)需要日語字符,而一些英語國家甚至簡單的ASCII字庫表就能滿足基本需求。而如果把每個(gè)字符都用字庫表中的序號(hào)來存儲(chǔ)的話,每個(gè)字符就需要3個(gè)字節(jié)(這里以Unicode字庫為例),這樣對(duì)于原本用僅占一個(gè)字符的ASCII編碼的英語地區(qū)國家顯然是一個(gè)額外成本(存儲(chǔ)體積是原來的三倍)。算的直接一些,同樣一塊硬盤,用ASCII可以存1500篇文章,而用3字節(jié)Unicode序號(hào)存儲(chǔ)只能存500篇。于是就出現(xiàn)了UTF-8這樣的變長編碼。在UTF-8編碼中原本只需要一個(gè)字節(jié)的ASCII字符,仍然只占一個(gè)字節(jié)。而像中文及日語這樣的復(fù)雜字符就需要2個(gè)到3個(gè)字節(jié)來存儲(chǔ)。
關(guān)于字符編碼知識(shí)的詳細(xì)講解請(qǐng)見:《字符編碼那點(diǎn)事:快速理解ASCII、Unicode、GBK和UTF-8》。
字符集只是一個(gè)規(guī)則集合的名字,對(duì)應(yīng)到真實(shí)生活中,字符集就是對(duì)某種語言的稱呼。例如:英語,漢語,日語。
對(duì)于一個(gè)字符集來說要正確編碼轉(zhuǎn)碼一個(gè)字符需要三個(gè)關(guān)鍵元素:
1)字庫表(character repertoire):是一個(gè)相當(dāng)于所有可讀或者可顯示字符的數(shù)據(jù)庫,字庫表決定了整個(gè)字符集能夠展現(xiàn)表示的所有字符的范圍;
2)編碼字符集(coded character set):即用一個(gè)編碼值code point來表示一個(gè)字符在字庫中的位置;
3)字符編碼(character encoding form):將編碼字符集和實(shí)際存儲(chǔ)數(shù)值之間的轉(zhuǎn)換關(guān)系。
一般來說都會(huì)直接將code point的值作為編碼后的值直接存儲(chǔ)。例如在ASCII中“A”在表中排第65位,而編碼后A的數(shù)值是 0100 0001 也即十進(jìn)制的65的二進(jìn)制轉(zhuǎn)換結(jié)果。
看到這里,可能很多讀者都會(huì)有和我當(dāng)初一樣的疑問:字庫表和編碼字符集看來是必不可少的,那既然字庫表中的每一個(gè)字符都有一個(gè)自己的序號(hào),直接把序號(hào)作為存儲(chǔ)內(nèi)容就好了。為什么還要多此一舉通過字符編碼把序號(hào)轉(zhuǎn)換成另外一種存儲(chǔ)格式呢?
其實(shí)原因也比較容易理解:統(tǒng)一字庫表的目的是為了能夠涵蓋世界上所有的字符,但實(shí)際使用過程中會(huì)發(fā)現(xiàn)真正用的上的字符相對(duì)整個(gè)字庫表來說比例非常低。例如中文地區(qū)的程序幾乎不會(huì)需要日語字符,而一些英語國家甚至簡單的ASCII字庫表就能滿足基本需求。而如果把每個(gè)字符都用字庫表中的序號(hào)來存儲(chǔ)的話,每個(gè)字符就需要3個(gè)字節(jié)(這里以Unicode字庫為例),這樣對(duì)于原本用僅占一個(gè)字符的ASCII編碼的英語地區(qū)國家顯然是一個(gè)額外成本(存儲(chǔ)體積是原來的三倍)。算的直接一些,同樣一塊硬盤,用ASCII可以存1500篇文章,而用3字節(jié)Unicode序號(hào)存儲(chǔ)只能存500篇。于是就出現(xiàn)了UTF-8這樣的變長編碼。在UTF-8編碼中原本只需要一個(gè)字節(jié)的ASCII字符,仍然只占一個(gè)字節(jié)。而像中文及日語這樣的復(fù)雜字符就需要2個(gè)到3個(gè)字節(jié)來存儲(chǔ)。
關(guān)于字符編碼知識(shí)的詳細(xì)講解請(qǐng)見:《字符編碼那點(diǎn)事:快速理解ASCII、Unicode、GBK和UTF-8》。
7、UTF-8和Unicode的關(guān)系
看完上面兩個(gè)概念解釋,那么解釋UTF-8和Unicode的關(guān)系就比較簡單了。
Unicode就是上文中提到的編碼字符集,而UTF-8就是字符編碼,即Unicode規(guī)則字庫的一種實(shí)現(xiàn)形式。
隨著互聯(lián)網(wǎng)的發(fā)展,對(duì)同一字庫集的要求越來越迫切,Unicode標(biāo)準(zhǔn)也就自然而然的出現(xiàn)。它幾乎涵蓋了各個(gè)國家語言可能出現(xiàn)的符號(hào)和文字,并將為他們編號(hào)。詳見:Unicode百科介紹。
Unicode的編號(hào)從 0000 開始一直到10FFFF 共分為17個(gè)Plane,每個(gè)Plane中有65536個(gè)字符。而UTF-8則只實(shí)現(xiàn)了第一個(gè)Plane,可見UTF-8雖然是一個(gè)當(dāng)今接受度最廣的字符集編碼,但是它并沒有涵蓋整個(gè)Unicode的字庫,這也造成了它在某些場景下對(duì)于特殊字符的處理困難(下文會(huì)有提到)。
看完上面兩個(gè)概念解釋,那么解釋UTF-8和Unicode的關(guān)系就比較簡單了。
Unicode就是上文中提到的編碼字符集,而UTF-8就是字符編碼,即Unicode規(guī)則字庫的一種實(shí)現(xiàn)形式。
隨著互聯(lián)網(wǎng)的發(fā)展,對(duì)同一字庫集的要求越來越迫切,Unicode標(biāo)準(zhǔn)也就自然而然的出現(xiàn)。它幾乎涵蓋了各個(gè)國家語言可能出現(xiàn)的符號(hào)和文字,并將為他們編號(hào)。詳見:Unicode百科介紹。
Unicode的編號(hào)從 0000 開始一直到10FFFF 共分為17個(gè)Plane,每個(gè)Plane中有65536個(gè)字符。而UTF-8則只實(shí)現(xiàn)了第一個(gè)Plane,可見UTF-8雖然是一個(gè)當(dāng)今接受度最廣的字符集編碼,但是它并沒有涵蓋整個(gè)Unicode的字庫,這也造成了它在某些場景下對(duì)于特殊字符的處理困難(下文會(huì)有提到)。
8、UTF-8編碼簡介
為了更好的理解后面的實(shí)際應(yīng)用,我們這里簡單的介紹下UTF-8的編碼實(shí)現(xiàn)方法。即UTF-8的物理存儲(chǔ)和Unicode序號(hào)的轉(zhuǎn)換關(guān)系。
UTF-8編碼為變長編碼,最小編碼單位(code unit)為一個(gè)字節(jié)。一個(gè)字節(jié)的前1-3個(gè)bit為描述性部分,后面為實(shí)際序號(hào)部分:
- 1)如果一個(gè)字節(jié)的第一位為0,那么代表當(dāng)前字符為單字節(jié)字符,占用一個(gè)字節(jié)的空間。0之后的所有部分(7個(gè)bit)代表在Unicode中的序號(hào);
- 2)如果一個(gè)字節(jié)以110開頭,那么代表當(dāng)前字符為雙字節(jié)字符,占用2個(gè)字節(jié)的空間。110之后的所有部分(5個(gè)bit)加上后一個(gè)字節(jié)的除10外的部分(6個(gè)bit)代表在Unicode中的序號(hào)。且第二個(gè)字節(jié)以10開頭;
- 3)如果一個(gè)字節(jié)以1110開頭,那么代表當(dāng)前字符為三字節(jié)字符,占用3個(gè)字節(jié)的空間。110之后的所有部分(5個(gè)bit)加上后兩個(gè)字節(jié)的除10外的部分(12個(gè)bit)代表在Unicode中的序號(hào)。且第二、第三個(gè)字節(jié)以10開頭;
- 4)如果一個(gè)字節(jié)以10開頭,那么代表當(dāng)前字節(jié)為多字節(jié)字符的第二個(gè)字節(jié)。10之后的所有部分(6個(gè)bit)和之前的部分一同組成在Unicode中的序號(hào)。
具體每個(gè)字節(jié)的特征可見下表,其中“x”代表序號(hào)部分,把各個(gè)字節(jié)中的所有x部分拼接在一起就組成了在Unicode字庫中的序號(hào)。如下圖所示。
我們分別看三個(gè)從一個(gè)字節(jié)到三個(gè)字節(jié)的UTF-8編碼例子:
細(xì)心的讀者不難從以上的簡單介紹中得出以下規(guī)律:
1)3個(gè)字節(jié)的UTF-8十六進(jìn)制編碼一定是以E開頭的;
2)2個(gè)字節(jié)的UTF-8十六進(jìn)制編碼一定是以C或D開頭的;
3)1個(gè)字節(jié)的UTF-8十六進(jìn)制編碼一定是以比8小的數(shù)字開頭的。
為了更好的理解后面的實(shí)際應(yīng)用,我們這里簡單的介紹下UTF-8的編碼實(shí)現(xiàn)方法。即UTF-8的物理存儲(chǔ)和Unicode序號(hào)的轉(zhuǎn)換關(guān)系。
UTF-8編碼為變長編碼,最小編碼單位(code unit)為一個(gè)字節(jié)。一個(gè)字節(jié)的前1-3個(gè)bit為描述性部分,后面為實(shí)際序號(hào)部分:
- 1)如果一個(gè)字節(jié)的第一位為0,那么代表當(dāng)前字符為單字節(jié)字符,占用一個(gè)字節(jié)的空間。0之后的所有部分(7個(gè)bit)代表在Unicode中的序號(hào);
- 2)如果一個(gè)字節(jié)以110開頭,那么代表當(dāng)前字符為雙字節(jié)字符,占用2個(gè)字節(jié)的空間。110之后的所有部分(5個(gè)bit)加上后一個(gè)字節(jié)的除10外的部分(6個(gè)bit)代表在Unicode中的序號(hào)。且第二個(gè)字節(jié)以10開頭;
- 3)如果一個(gè)字節(jié)以1110開頭,那么代表當(dāng)前字符為三字節(jié)字符,占用3個(gè)字節(jié)的空間。110之后的所有部分(5個(gè)bit)加上后兩個(gè)字節(jié)的除10外的部分(12個(gè)bit)代表在Unicode中的序號(hào)。且第二、第三個(gè)字節(jié)以10開頭;
- 4)如果一個(gè)字節(jié)以10開頭,那么代表當(dāng)前字節(jié)為多字節(jié)字符的第二個(gè)字節(jié)。10之后的所有部分(6個(gè)bit)和之前的部分一同組成在Unicode中的序號(hào)。
具體每個(gè)字節(jié)的特征可見下表,其中“x”代表序號(hào)部分,把各個(gè)字節(jié)中的所有x部分拼接在一起就組成了在Unicode字庫中的序號(hào)。如下圖所示。

我們分別看三個(gè)從一個(gè)字節(jié)到三個(gè)字節(jié)的UTF-8編碼例子:

細(xì)心的讀者不難從以上的簡單介紹中得出以下規(guī)律:
1)3個(gè)字節(jié)的UTF-8十六進(jìn)制編碼一定是以E開頭的;
2)2個(gè)字節(jié)的UTF-8十六進(jìn)制編碼一定是以C或D開頭的;
3)1個(gè)字節(jié)的UTF-8十六進(jìn)制編碼一定是以比8小的數(shù)字開頭的。
9、為什么會(huì)出現(xiàn)亂碼
亂碼也就是英文常說的mojibake(由日語的文字化け音譯)。
簡單的說亂碼的出現(xiàn)是因?yàn)椋壕幋a和解碼時(shí)用了不同或者不兼容的字符集。
對(duì)應(yīng)到真實(shí)生活中:就好比是一個(gè)英國人為了表示祝福在紙上寫了bless(編碼過程)。而一個(gè)法國人拿到了這張紙,由于在法語中bless表示受傷的意思,所以認(rèn)為他想表達(dá)的是受傷(解碼過程)。這個(gè)就是一個(gè)現(xiàn)實(shí)生活中的亂碼情況。
在計(jì)算機(jī)科學(xué)中一樣:一個(gè)用UTF-8編碼后的字符,用GBK去解碼。由于兩個(gè)字符集的字庫表不一樣,同一個(gè)漢字在兩個(gè)字符表的位置也不同,最終就會(huì)出現(xiàn)亂碼。
我們來看一個(gè)例子,假設(shè)我們用UTF-8編碼存儲(chǔ)“很屌”兩個(gè)字,會(huì)有如下轉(zhuǎn)換:
于是我們得到了E5BE88E5B18C這么一串?dāng)?shù)值,而顯示時(shí)我們用GBK解碼進(jìn)行展示,通過查表我們獲得以下信息:

解碼后我們就得到了“寰堝睂”這么一個(gè)錯(cuò)誤的結(jié)果,更要命的是連字符個(gè)數(shù)都變了。
亂碼也就是英文常說的mojibake(由日語的文字化け音譯)。
簡單的說亂碼的出現(xiàn)是因?yàn)椋壕幋a和解碼時(shí)用了不同或者不兼容的字符集。
對(duì)應(yīng)到真實(shí)生活中:就好比是一個(gè)英國人為了表示祝福在紙上寫了bless(編碼過程)。而一個(gè)法國人拿到了這張紙,由于在法語中bless表示受傷的意思,所以認(rèn)為他想表達(dá)的是受傷(解碼過程)。這個(gè)就是一個(gè)現(xiàn)實(shí)生活中的亂碼情況。
在計(jì)算機(jī)科學(xué)中一樣:一個(gè)用UTF-8編碼后的字符,用GBK去解碼。由于兩個(gè)字符集的字庫表不一樣,同一個(gè)漢字在兩個(gè)字符表的位置也不同,最終就會(huì)出現(xiàn)亂碼。
我們來看一個(gè)例子,假設(shè)我們用UTF-8編碼存儲(chǔ)“很屌”兩個(gè)字,會(huì)有如下轉(zhuǎn)換:

于是我們得到了E5BE88E5B18C這么一串?dāng)?shù)值,而顯示時(shí)我們用GBK解碼進(jìn)行展示,通過查表我們獲得以下信息:

解碼后我們就得到了“寰堝睂”這么一個(gè)錯(cuò)誤的結(jié)果,更要命的是連字符個(gè)數(shù)都變了。
10、如何識(shí)別亂碼的本來想要表達(dá)的文字
要從亂碼字符中反解出原來的正確文字需要對(duì)各個(gè)字符集編碼規(guī)則有較為深刻的掌握。但是原理很簡單,這里用以MySQL數(shù)據(jù)庫中的數(shù)據(jù)操縱中最常見的UTF-8被錯(cuò)誤用GBK展示時(shí)的亂碼為例,來說明具體反解和識(shí)別過程。
要從亂碼字符中反解出原來的正確文字需要對(duì)各個(gè)字符集編碼規(guī)則有較為深刻的掌握。但是原理很簡單,這里用以MySQL數(shù)據(jù)庫中的數(shù)據(jù)操縱中最常見的UTF-8被錯(cuò)誤用GBK展示時(shí)的亂碼為例,來說明具體反解和識(shí)別過程。
10.1 第1步:編碼
假設(shè)我們?cè)陧撁嫔峡吹?#8220;寰堝睂”這樣的亂碼,而又得知我們的瀏覽器當(dāng)前使用GBK編碼。那么第一步我們就能先通過GBK把亂碼編碼成二進(jìn)制表達(dá)式。
當(dāng)然查表編碼效率很低,我們也可以用以下SQL語句直接通過MySQL客戶端來做編碼工作:
mysql [localhost] {msandbox} > selecthex(convert('寰堝睂'using gbk));
+-------------------------------------+
| hex(convert('寰堝睂'using gbk)) |
+-------------------------------------+
| E5BE88E5B18C |
+-------------------------------------+
1 row inset(0.01 sec)
假設(shè)我們?cè)陧撁嫔峡吹?#8220;寰堝睂”這樣的亂碼,而又得知我們的瀏覽器當(dāng)前使用GBK編碼。那么第一步我們就能先通過GBK把亂碼編碼成二進(jìn)制表達(dá)式。
當(dāng)然查表編碼效率很低,我們也可以用以下SQL語句直接通過MySQL客戶端來做編碼工作:
mysql [localhost] {msandbox} > selecthex(convert('寰堝睂'using gbk));
+-------------------------------------+
| hex(convert('寰堝睂'using gbk)) |
+-------------------------------------+
| E5BE88E5B18C |
+-------------------------------------+
1 row inset(0.01 sec)
10.2 第2步:識(shí)別
現(xiàn)在我們得到了解碼后的二進(jìn)制字符串E5BE88E5B18C。然后我們將它按字節(jié)拆開。

然后套用之前UTF-8編碼介紹章節(jié)中總結(jié)出的規(guī)律,就不難發(fā)現(xiàn)這6個(gè)字節(jié)的數(shù)據(jù)符合UTF-8編碼規(guī)則。如果整個(gè)數(shù)據(jù)流都符合這個(gè)規(guī)則的話,我們就能大膽假設(shè)亂碼之前的編碼字符集是UTF-8。
現(xiàn)在我們得到了解碼后的二進(jìn)制字符串E5BE88E5B18C。然后我們將它按字節(jié)拆開。

然后套用之前UTF-8編碼介紹章節(jié)中總結(jié)出的規(guī)律,就不難發(fā)現(xiàn)這6個(gè)字節(jié)的數(shù)據(jù)符合UTF-8編碼規(guī)則。如果整個(gè)數(shù)據(jù)流都符合這個(gè)規(guī)則的話,我們就能大膽假設(shè)亂碼之前的編碼字符集是UTF-8。
10.3 第3步:解碼
然后我們就能拿著 E5BE88E5B18C 用UTF-8解碼,查看亂碼前的文字了。
當(dāng)然我們可以不查表直接通過SQL獲得結(jié)果:
mysql [localhost] {msandbox} ((none)) > selectconvert(0xE5BE88E5B18C using utf8);
+------------------------------------+
| convert(0xE5BE88E5B18C using utf8) |
+------------------------------------+
| 很屌 |
+------------------------------------+
1 row inset(0.00 sec)
然后我們就能拿著 E5BE88E5B18C 用UTF-8解碼,查看亂碼前的文字了。
當(dāng)然我們可以不查表直接通過SQL獲得結(jié)果:
mysql [localhost] {msandbox} ((none)) > selectconvert(0xE5BE88E5B18C using utf8);
+------------------------------------+
| convert(0xE5BE88E5B18C using utf8) |
+------------------------------------+
| 很屌 |
+------------------------------------+
1 row inset(0.00 sec)
11、常見的IM亂碼問題處理之MySQL中的Emoji字符
所謂Emoji就是一種在Unicode位于 \u1F601-\u1F64F 區(qū)段的字符。這個(gè)顯然超過了目前常用的UTF-8字符集的編碼范圍 \u0000-\uFFFF。Emoji表情隨著IOS的普及和微信的支持越來越常見。
下面就是幾個(gè)常見的Emoji(IM聊天軟件中經(jīng)常會(huì)被用到):

那么Emoji字符表情會(huì)對(duì)我們平時(shí)的開發(fā)運(yùn)維帶來什么影響呢?
最常見的問題就在于將他存入MySQL數(shù)據(jù)庫的時(shí)候。一般來說MySQL數(shù)據(jù)庫的默認(rèn)字符集都會(huì)配置成UTF-8(三字節(jié)),而utf8mb4在5.5以后才被支持,也很少會(huì)有DBA主動(dòng)將系統(tǒng)默認(rèn)字符集改成utf8mb4。
那么問題就來了,當(dāng)我們把一個(gè)需要4字節(jié)UTF-8編碼才能表示的字符存入數(shù)據(jù)庫的時(shí)候就會(huì)報(bào)錯(cuò):ERROR 1366: Incorrect string value: '\xF0\x9D\x8C\x86' for column 。
如果認(rèn)真閱讀了上面的解釋,那么這個(gè)報(bào)錯(cuò)也就不難看懂了:我們?cè)噲D將一串Bytes插入到一列中,而這串Bytes的第一個(gè)字節(jié)是 \xF0 意味著這是一個(gè)四字節(jié)的UTF-8編碼。但是當(dāng)MySQL表和列字符集配置為UTF-8的時(shí)候是無法存儲(chǔ)這樣的字符的,所以報(bào)了錯(cuò)。
那么遇到這種情況我們?nèi)绾谓鉀Q呢?
有兩種方式:
- 1)升級(jí)MySQL到5.6或更高版本,并且將表字符集切換至utf8mb4;
- 2)在把內(nèi)容存入到數(shù)據(jù)庫之前做一次過濾,將Emoji字符替換成一段特殊的文字編碼,然后再存入數(shù)據(jù)庫中。之后從數(shù)據(jù)庫獲取或者前端展示時(shí)再將這段特殊文字編碼轉(zhuǎn)換成Emoji顯示。
第二種方法我們假設(shè)用 -*-1F601-*- 來替代4字節(jié)的Emoji,那么具體實(shí)現(xiàn)python代碼可以參見Stackoverflow上的回答。
所謂Emoji就是一種在Unicode位于 \u1F601-\u1F64F 區(qū)段的字符。這個(gè)顯然超過了目前常用的UTF-8字符集的編碼范圍 \u0000-\uFFFF。Emoji表情隨著IOS的普及和微信的支持越來越常見。
下面就是幾個(gè)常見的Emoji(IM聊天軟件中經(jīng)常會(huì)被用到):

那么Emoji字符表情會(huì)對(duì)我們平時(shí)的開發(fā)運(yùn)維帶來什么影響呢?
最常見的問題就在于將他存入MySQL數(shù)據(jù)庫的時(shí)候。一般來說MySQL數(shù)據(jù)庫的默認(rèn)字符集都會(huì)配置成UTF-8(三字節(jié)),而utf8mb4在5.5以后才被支持,也很少會(huì)有DBA主動(dòng)將系統(tǒng)默認(rèn)字符集改成utf8mb4。
那么問題就來了,當(dāng)我們把一個(gè)需要4字節(jié)UTF-8編碼才能表示的字符存入數(shù)據(jù)庫的時(shí)候就會(huì)報(bào)錯(cuò):ERROR 1366: Incorrect string value: '\xF0\x9D\x8C\x86' for column 。
如果認(rèn)真閱讀了上面的解釋,那么這個(gè)報(bào)錯(cuò)也就不難看懂了:我們?cè)噲D將一串Bytes插入到一列中,而這串Bytes的第一個(gè)字節(jié)是 \xF0 意味著這是一個(gè)四字節(jié)的UTF-8編碼。但是當(dāng)MySQL表和列字符集配置為UTF-8的時(shí)候是無法存儲(chǔ)這樣的字符的,所以報(bào)了錯(cuò)。
那么遇到這種情況我們?nèi)绾谓鉀Q呢?
有兩種方式:
- 1)升級(jí)MySQL到5.6或更高版本,并且將表字符集切換至utf8mb4;
- 2)在把內(nèi)容存入到數(shù)據(jù)庫之前做一次過濾,將Emoji字符替換成一段特殊的文字編碼,然后再存入數(shù)據(jù)庫中。之后從數(shù)據(jù)庫獲取或者前端展示時(shí)再將這段特殊文字編碼轉(zhuǎn)換成Emoji顯示。
第二種方法我們假設(shè)用 -*-1F601-*- 來替代4字節(jié)的Emoji,那么具體實(shí)現(xiàn)python代碼可以參見Stackoverflow上的回答。
12、參考文獻(xiàn)
附錄:更多IM開發(fā)方面的文章
[1] IM開發(fā)綜合文章:
《新手入門一篇就夠:從零開發(fā)移動(dòng)端IM》
《移動(dòng)端IM開發(fā)者必讀(一):通俗易懂,理解移動(dòng)網(wǎng)絡(luò)的“弱”和“慢”》
《移動(dòng)端IM開發(fā)者必讀(二):史上最全移動(dòng)弱網(wǎng)絡(luò)優(yōu)化方法總結(jié)》
《從客戶端的角度來談?wù)勔苿?dòng)端IM的消息可靠性和送達(dá)機(jī)制》
《現(xiàn)代移動(dòng)端網(wǎng)絡(luò)短連接的優(yōu)化手段總結(jié):請(qǐng)求速度、弱網(wǎng)適應(yīng)、安全保障》
《騰訊技術(shù)分享:社交網(wǎng)絡(luò)圖片的帶寬壓縮技術(shù)演進(jìn)之路》
《小白必讀:閑話HTTP短連接中的Session和Token》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課:正確理解前置HTTP SSO單點(diǎn)登陸接口的原理》
《移動(dòng)端IM開發(fā)需要面對(duì)的技術(shù)問題》
《開發(fā)IM是自己設(shè)計(jì)協(xié)議用字節(jié)流好還是字符流好?》
《請(qǐng)問有人知道語音留言聊天的主流實(shí)現(xiàn)方式嗎?》
《完全自已開發(fā)的IM該如何設(shè)計(jì)“失敗重試”機(jī)制?》
《通俗易懂:基于集群的移動(dòng)端IM接入層負(fù)載均衡方案分享》
《微信對(duì)網(wǎng)絡(luò)影響的技術(shù)試驗(yàn)及分析(論文全文)》
《即時(shí)通訊系統(tǒng)的原理、技術(shù)和應(yīng)用(技術(shù)論文)》
《開源IM工程“蘑菇街TeamTalk”的現(xiàn)狀:一場有始無終的開源秀》
《QQ音樂團(tuán)隊(duì)分享:Android中的圖片壓縮技術(shù)詳解(上篇)》
《QQ音樂團(tuán)隊(duì)分享:Android中的圖片壓縮技術(shù)詳解(下篇)》
《騰訊原創(chuàng)分享(一):如何大幅提升移動(dòng)網(wǎng)絡(luò)下手機(jī)QQ的圖片傳輸速度和成功率》
《騰訊原創(chuàng)分享(二):如何大幅壓縮移動(dòng)網(wǎng)絡(luò)下APP的流量消耗(上篇)》
《騰訊原創(chuàng)分享(三):如何大幅壓縮移動(dòng)網(wǎng)絡(luò)下APP的流量消耗(下篇)》
《如約而至:微信自用的移動(dòng)端IM網(wǎng)絡(luò)層跨平臺(tái)組件庫Mars已正式開源》
《基于社交網(wǎng)絡(luò)的Yelp是如何實(shí)現(xiàn)海量用戶圖片的無損壓縮的?》
《騰訊技術(shù)分享:騰訊是如何大幅降低帶寬和網(wǎng)絡(luò)流量的(圖片壓縮篇)》
《騰訊技術(shù)分享:騰訊是如何大幅降低帶寬和網(wǎng)絡(luò)流量的(音視頻技術(shù)篇)》
《字符編碼那點(diǎn)事:快速理解ASCII、Unicode、GBK和UTF-8》
《全面掌握移動(dòng)端主流圖片格式的特點(diǎn)、性能、調(diào)優(yōu)等》
《子彈短信光鮮的背后:網(wǎng)易云信首席架構(gòu)師分享億級(jí)IM平臺(tái)的技術(shù)實(shí)踐》
《微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)》
《自已開發(fā)IM有那么難嗎?手把手教你自擼一個(gè)Andriod版簡易IM (有源碼)》
《融云技術(shù)分享:解密融云IM產(chǎn)品的聊天消息ID生成策略》
《適合新手:從零開發(fā)一個(gè)IM服務(wù)端(基于Netty,有完整源碼)》
《拿起鍵盤就是干:跟我一起徒手開發(fā)一套分布式IM系統(tǒng)》
>> 更多同類文章 ……
[2] 有關(guān)IM架構(gòu)設(shè)計(jì)的文章:
《淺談IM系統(tǒng)的架構(gòu)設(shè)計(jì)》
《簡述移動(dòng)端IM開發(fā)的那些坑:架構(gòu)設(shè)計(jì)、通信協(xié)議和客戶端》
《一套海量在線用戶的移動(dòng)端IM架構(gòu)設(shè)計(jì)實(shí)踐分享(含詳細(xì)圖文)》
《一套原創(chuàng)分布式即時(shí)通訊(IM)系統(tǒng)理論架構(gòu)方案》
《從零到卓越:京東客服即時(shí)通訊系統(tǒng)的技術(shù)架構(gòu)演進(jìn)歷程》
《蘑菇街即時(shí)通訊/IM服務(wù)器開發(fā)之架構(gòu)選擇》
《騰訊QQ1.4億在線用戶的技術(shù)挑戰(zhàn)和架構(gòu)演進(jìn)之路PPT》
《微信后臺(tái)基于時(shí)間序的海量數(shù)據(jù)冷熱分級(jí)架構(gòu)設(shè)計(jì)實(shí)踐》
《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(演講全文)》
《如何解讀《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡》》
《快速裂變:見證微信強(qiáng)大后臺(tái)架構(gòu)從0到1的演進(jìn)歷程(一)》
《17年的實(shí)踐:騰訊海量產(chǎn)品的技術(shù)方法論》
《移動(dòng)端IM中大規(guī)模群消息的推送如何保證效率、實(shí)時(shí)性?》
《現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(二):如何設(shè)計(jì)大量圖片文件的服務(wù)端存儲(chǔ)架構(gòu)?》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(三):快速理解服務(wù)端數(shù)據(jù)庫讀寫分離原理及實(shí)踐建議》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(四):正確理解HTTP短連接中的Cookie、Session和Token》
《WhatsApp技術(shù)實(shí)踐分享:32人工程團(tuán)隊(duì)創(chuàng)造的技術(shù)神話》
《微信朋友圈千億訪問量背后的技術(shù)挑戰(zhàn)和實(shí)踐總結(jié)》
《王者榮耀2億用戶量的背后:產(chǎn)品定位、技術(shù)架構(gòu)、網(wǎng)絡(luò)方案等》
《IM系統(tǒng)的MQ消息中間件選型:Kafka還是RabbitMQ?》
《騰訊資深架構(gòu)師干貨總結(jié):一文讀懂大型分布式系統(tǒng)設(shè)計(jì)的方方面面》
《以微博類應(yīng)用場景為例,總結(jié)海量社交系統(tǒng)的架構(gòu)設(shè)計(jì)步驟》
《快速理解高性能HTTP服務(wù)端的負(fù)載均衡技術(shù)原理》
《子彈短信光鮮的背后:網(wǎng)易云信首席架構(gòu)師分享億級(jí)IM平臺(tái)的技術(shù)實(shí)踐》
《知乎技術(shù)分享:從單機(jī)到2000萬QPS并發(fā)的Redis高性能緩存實(shí)踐之路》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(五):通俗易懂,正確理解并用好MQ消息隊(duì)列》
《微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)》
《微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(容災(zāi)方案篇)》
《新手入門:零基礎(chǔ)理解大型分布式架構(gòu)的演進(jìn)歷史、技術(shù)原理、最佳實(shí)踐》
《一套高可用、易伸縮、高并發(fā)的IM群聊、單聊架構(gòu)方案設(shè)計(jì)實(shí)踐》
《阿里技術(shù)分享:深度揭秘阿里數(shù)據(jù)庫技術(shù)方案的10年變遷史》
《阿里技術(shù)分享:阿里自研金融級(jí)數(shù)據(jù)庫OceanBase的艱辛成長之路》
《社交軟件紅包技術(shù)解密(一):全面解密QQ紅包技術(shù)方案——架構(gòu)、技術(shù)實(shí)現(xiàn)等》
《社交軟件紅包技術(shù)解密(二):解密微信搖一搖紅包從0到1的技術(shù)演進(jìn)》
《社交軟件紅包技術(shù)解密(三):微信搖一搖紅包雨背后的技術(shù)細(xì)節(jié)》
《社交軟件紅包技術(shù)解密(四):微信紅包系統(tǒng)是如何應(yīng)對(duì)高并發(fā)的》
《社交軟件紅包技術(shù)解密(五):微信紅包系統(tǒng)是如何實(shí)現(xiàn)高可用性的》
《社交軟件紅包技術(shù)解密(六):微信紅包系統(tǒng)的存儲(chǔ)層架構(gòu)演進(jìn)實(shí)踐》
《社交軟件紅包技術(shù)解密(七):支付寶紅包的海量高并發(fā)技術(shù)實(shí)踐》
《社交軟件紅包技術(shù)解密(八):全面解密微博紅包技術(shù)方案》
《社交軟件紅包技術(shù)解密(九):談?wù)勈諵紅包的功能邏輯、容災(zāi)、運(yùn)維、架構(gòu)等》
《即時(shí)通訊新手入門:一文讀懂什么是Nginx?它能否實(shí)現(xiàn)IM的負(fù)載均衡?》
《即時(shí)通訊新手入門:快速理解RPC技術(shù)——基本概念、原理和用途》
《多維度對(duì)比5款主流分布式MQ消息隊(duì)列,媽媽再也不擔(dān)心我的技術(shù)選型了》
《從游擊隊(duì)到正規(guī)軍(一):馬蜂窩旅游網(wǎng)的IM系統(tǒng)架構(gòu)演進(jìn)之路》
《從游擊隊(duì)到正規(guī)軍(二):馬蜂窩旅游網(wǎng)的IM客戶端架構(gòu)演進(jìn)和實(shí)踐總結(jié)》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(六):數(shù)據(jù)庫用NoSQL還是SQL?讀這篇就夠了!》
《瓜子IM智能客服系統(tǒng)的數(shù)據(jù)架構(gòu)設(shè)計(jì)(整理自現(xiàn)場演講,有配套PPT)》
《阿里釘釘技術(shù)分享:企業(yè)級(jí)IM王者——釘釘在后端架構(gòu)上的過人之處》
>> 更多同類文章 ……
[1] IM開發(fā)綜合文章:
《新手入門一篇就夠:從零開發(fā)移動(dòng)端IM》
《移動(dòng)端IM開發(fā)者必讀(一):通俗易懂,理解移動(dòng)網(wǎng)絡(luò)的“弱”和“慢”》
《移動(dòng)端IM開發(fā)者必讀(二):史上最全移動(dòng)弱網(wǎng)絡(luò)優(yōu)化方法總結(jié)》
《從客戶端的角度來談?wù)勔苿?dòng)端IM的消息可靠性和送達(dá)機(jī)制》
《現(xiàn)代移動(dòng)端網(wǎng)絡(luò)短連接的優(yōu)化手段總結(jié):請(qǐng)求速度、弱網(wǎng)適應(yīng)、安全保障》
《騰訊技術(shù)分享:社交網(wǎng)絡(luò)圖片的帶寬壓縮技術(shù)演進(jìn)之路》
《小白必讀:閑話HTTP短連接中的Session和Token》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課:正確理解前置HTTP SSO單點(diǎn)登陸接口的原理》
《移動(dòng)端IM開發(fā)需要面對(duì)的技術(shù)問題》
《開發(fā)IM是自己設(shè)計(jì)協(xié)議用字節(jié)流好還是字符流好?》
《請(qǐng)問有人知道語音留言聊天的主流實(shí)現(xiàn)方式嗎?》
《完全自已開發(fā)的IM該如何設(shè)計(jì)“失敗重試”機(jī)制?》
《通俗易懂:基于集群的移動(dòng)端IM接入層負(fù)載均衡方案分享》
《微信對(duì)網(wǎng)絡(luò)影響的技術(shù)試驗(yàn)及分析(論文全文)》
《即時(shí)通訊系統(tǒng)的原理、技術(shù)和應(yīng)用(技術(shù)論文)》
《開源IM工程“蘑菇街TeamTalk”的現(xiàn)狀:一場有始無終的開源秀》
《QQ音樂團(tuán)隊(duì)分享:Android中的圖片壓縮技術(shù)詳解(上篇)》
《QQ音樂團(tuán)隊(duì)分享:Android中的圖片壓縮技術(shù)詳解(下篇)》
《騰訊原創(chuàng)分享(一):如何大幅提升移動(dòng)網(wǎng)絡(luò)下手機(jī)QQ的圖片傳輸速度和成功率》
《騰訊原創(chuàng)分享(二):如何大幅壓縮移動(dòng)網(wǎng)絡(luò)下APP的流量消耗(上篇)》
《騰訊原創(chuàng)分享(三):如何大幅壓縮移動(dòng)網(wǎng)絡(luò)下APP的流量消耗(下篇)》
《如約而至:微信自用的移動(dòng)端IM網(wǎng)絡(luò)層跨平臺(tái)組件庫Mars已正式開源》
《基于社交網(wǎng)絡(luò)的Yelp是如何實(shí)現(xiàn)海量用戶圖片的無損壓縮的?》
《騰訊技術(shù)分享:騰訊是如何大幅降低帶寬和網(wǎng)絡(luò)流量的(圖片壓縮篇)》
《騰訊技術(shù)分享:騰訊是如何大幅降低帶寬和網(wǎng)絡(luò)流量的(音視頻技術(shù)篇)》
《字符編碼那點(diǎn)事:快速理解ASCII、Unicode、GBK和UTF-8》
《全面掌握移動(dòng)端主流圖片格式的特點(diǎn)、性能、調(diào)優(yōu)等》
《子彈短信光鮮的背后:網(wǎng)易云信首席架構(gòu)師分享億級(jí)IM平臺(tái)的技術(shù)實(shí)踐》
《微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)》
《自已開發(fā)IM有那么難嗎?手把手教你自擼一個(gè)Andriod版簡易IM (有源碼)》
《融云技術(shù)分享:解密融云IM產(chǎn)品的聊天消息ID生成策略》
《適合新手:從零開發(fā)一個(gè)IM服務(wù)端(基于Netty,有完整源碼)》
《拿起鍵盤就是干:跟我一起徒手開發(fā)一套分布式IM系統(tǒng)》
>> 更多同類文章 ……
[2] 有關(guān)IM架構(gòu)設(shè)計(jì)的文章:
《淺談IM系統(tǒng)的架構(gòu)設(shè)計(jì)》
《簡述移動(dòng)端IM開發(fā)的那些坑:架構(gòu)設(shè)計(jì)、通信協(xié)議和客戶端》
《一套海量在線用戶的移動(dòng)端IM架構(gòu)設(shè)計(jì)實(shí)踐分享(含詳細(xì)圖文)》
《一套原創(chuàng)分布式即時(shí)通訊(IM)系統(tǒng)理論架構(gòu)方案》
《從零到卓越:京東客服即時(shí)通訊系統(tǒng)的技術(shù)架構(gòu)演進(jìn)歷程》
《蘑菇街即時(shí)通訊/IM服務(wù)器開發(fā)之架構(gòu)選擇》
《騰訊QQ1.4億在線用戶的技術(shù)挑戰(zhàn)和架構(gòu)演進(jìn)之路PPT》
《微信后臺(tái)基于時(shí)間序的海量數(shù)據(jù)冷熱分級(jí)架構(gòu)設(shè)計(jì)實(shí)踐》
《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡(演講全文)》
《如何解讀《微信技術(shù)總監(jiān)談架構(gòu):微信之道——大道至簡》》
《快速裂變:見證微信強(qiáng)大后臺(tái)架構(gòu)從0到1的演進(jìn)歷程(一)》
《17年的實(shí)踐:騰訊海量產(chǎn)品的技術(shù)方法論》
《移動(dòng)端IM中大規(guī)模群消息的推送如何保證效率、實(shí)時(shí)性?》
《現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(二):如何設(shè)計(jì)大量圖片文件的服務(wù)端存儲(chǔ)架構(gòu)?》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(三):快速理解服務(wù)端數(shù)據(jù)庫讀寫分離原理及實(shí)踐建議》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(四):正確理解HTTP短連接中的Cookie、Session和Token》
《WhatsApp技術(shù)實(shí)踐分享:32人工程團(tuán)隊(duì)創(chuàng)造的技術(shù)神話》
《微信朋友圈千億訪問量背后的技術(shù)挑戰(zhàn)和實(shí)踐總結(jié)》
《王者榮耀2億用戶量的背后:產(chǎn)品定位、技術(shù)架構(gòu)、網(wǎng)絡(luò)方案等》
《IM系統(tǒng)的MQ消息中間件選型:Kafka還是RabbitMQ?》
《騰訊資深架構(gòu)師干貨總結(jié):一文讀懂大型分布式系統(tǒng)設(shè)計(jì)的方方面面》
《以微博類應(yīng)用場景為例,總結(jié)海量社交系統(tǒng)的架構(gòu)設(shè)計(jì)步驟》
《快速理解高性能HTTP服務(wù)端的負(fù)載均衡技術(shù)原理》
《子彈短信光鮮的背后:網(wǎng)易云信首席架構(gòu)師分享億級(jí)IM平臺(tái)的技術(shù)實(shí)踐》
《知乎技術(shù)分享:從單機(jī)到2000萬QPS并發(fā)的Redis高性能緩存實(shí)踐之路》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(五):通俗易懂,正確理解并用好MQ消息隊(duì)列》
《微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(算法原理篇)》
《微信技術(shù)分享:微信的海量IM聊天消息序列號(hào)生成實(shí)踐(容災(zāi)方案篇)》
《新手入門:零基礎(chǔ)理解大型分布式架構(gòu)的演進(jìn)歷史、技術(shù)原理、最佳實(shí)踐》
《一套高可用、易伸縮、高并發(fā)的IM群聊、單聊架構(gòu)方案設(shè)計(jì)實(shí)踐》
《阿里技術(shù)分享:深度揭秘阿里數(shù)據(jù)庫技術(shù)方案的10年變遷史》
《阿里技術(shù)分享:阿里自研金融級(jí)數(shù)據(jù)庫OceanBase的艱辛成長之路》
《社交軟件紅包技術(shù)解密(一):全面解密QQ紅包技術(shù)方案——架構(gòu)、技術(shù)實(shí)現(xiàn)等》
《社交軟件紅包技術(shù)解密(二):解密微信搖一搖紅包從0到1的技術(shù)演進(jìn)》
《社交軟件紅包技術(shù)解密(三):微信搖一搖紅包雨背后的技術(shù)細(xì)節(jié)》
《社交軟件紅包技術(shù)解密(四):微信紅包系統(tǒng)是如何應(yīng)對(duì)高并發(fā)的》
《社交軟件紅包技術(shù)解密(五):微信紅包系統(tǒng)是如何實(shí)現(xiàn)高可用性的》
《社交軟件紅包技術(shù)解密(六):微信紅包系統(tǒng)的存儲(chǔ)層架構(gòu)演進(jìn)實(shí)踐》
《社交軟件紅包技術(shù)解密(七):支付寶紅包的海量高并發(fā)技術(shù)實(shí)踐》
《社交軟件紅包技術(shù)解密(八):全面解密微博紅包技術(shù)方案》
《社交軟件紅包技術(shù)解密(九):談?wù)勈諵紅包的功能邏輯、容災(zāi)、運(yùn)維、架構(gòu)等》
《即時(shí)通訊新手入門:一文讀懂什么是Nginx?它能否實(shí)現(xiàn)IM的負(fù)載均衡?》
《即時(shí)通訊新手入門:快速理解RPC技術(shù)——基本概念、原理和用途》
《多維度對(duì)比5款主流分布式MQ消息隊(duì)列,媽媽再也不擔(dān)心我的技術(shù)選型了》
《從游擊隊(duì)到正規(guī)軍(一):馬蜂窩旅游網(wǎng)的IM系統(tǒng)架構(gòu)演進(jìn)之路》
《從游擊隊(duì)到正規(guī)軍(二):馬蜂窩旅游網(wǎng)的IM客戶端架構(gòu)演進(jìn)和實(shí)踐總結(jié)》
《IM開發(fā)基礎(chǔ)知識(shí)補(bǔ)課(六):數(shù)據(jù)庫用NoSQL還是SQL?讀這篇就夠了!》
《瓜子IM智能客服系統(tǒng)的數(shù)據(jù)架構(gòu)設(shè)計(jì)(整理自現(xiàn)場演講,有配套PPT)》
《阿里釘釘技術(shù)分享:企業(yè)級(jí)IM王者——釘釘在后端架構(gòu)上的過人之處》
>> 更多同類文章 ……
(本文同步發(fā)布于:http://www.52im.net/thread-2868-1-1.html)
作者:Jack Jiang (點(diǎn)擊作者姓名進(jìn)入Github)
出處:http://www.52im.net/space-uid-1.html
交流:歡迎加入即時(shí)通訊開發(fā)交流群 215891622
討論:http://www.52im.net/
Jack Jiang同時(shí)是【原創(chuàng)Java
Swing外觀工程BeautyEye】和【輕量級(jí)移動(dòng)端即時(shí)通訊框架MobileIMSDK】的作者,可前往下載交流。
本博文
歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處(也可前往 我的52im.net 找到我)。