亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

jvm file.encoding屬性引起的HBase亂碼問題怎么解決

發布時間:2021-12-09 13:57:03 來源:億速云 閱讀:124 作者:iii 欄目:云計算

這篇文章主要介紹“jvm file.encoding屬性引起的HBase亂碼問題怎么解決”,在日常操作中,相信很多人在jvm file.encoding屬性引起的HBase亂碼問題怎么解決問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”jvm file.encoding屬性引起的HBase亂碼問題怎么解決”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

1、問題:

最近在往 HBase 寫中文的時候,發現 hbase 查出來的數據會有部分中文亂碼了,而部分中文又是正常的,按理來說,一般的亂碼問題要么全亂,要么不亂。考慮到出現中文的地方都是來源于 hdfs 上的一個配置文件,而這個配置文件可以確定是 utf-8 編碼的,那排除了原始文件導致的亂碼,想想 MR 代碼里也沒有轉碼的邏輯,也排除了代碼的問題,那就只有一種可能:Hadoop 集群的系統環境是異構的,這里面可能涉及到 linux 、java 的環境變量、配置的問題。

2、排查:

(1)打印了整個集群的 echo $LANG、echo $LC_ALL 等linux系統變量,發現都是一致的,排除了 os 環境的問題。

(2)剩下的重點放在了 java 環境上,在代碼里加上如下兩句,打印每條記錄的 ip 和 jvm 編碼,然后看看亂碼的記錄是那臺機器產生的,并且當時 jvm child 的編碼情況:

java.net.InetAddress test = java.net.InetAddress.getByName("localhost");
put.add(Bytes.toBytes("cf"), Bytes.toBytes("ip"), Bytes.toBytes(test.getLocalHost().getHostAddress()));
put.add(Bytes.toBytes("cf"), Bytes.toBytes("ec"), Bytes.toBytes(System.getProperty("file.encoding")));

同時也直接  System.out.println 出相應的中文字段,看是寫進 hbase 之前還是之后亂掉的。

跑了一份測試數據后,發現 hbase 里的 ip、jvm 編碼是沒有規律的,然后查看 syso 打印的 log 發現,在寫 hbase 之前已經就已經亂碼了,然后想想 hbase 里的數據亂碼之所以沒有規律是因為 map 后要 shuffle、reduce 才能到 hbase。PS:sysout本身無編碼概念,類似 linux 下的 cat、head、more 等。

然后再次把 ip、jvm編碼 統計代碼放到 map 階段輸出,果真發現了規律,集群中有兩臺機器的 jvm 編碼不一致,不是 utf-8 的:

jvm file.encoding屬性引起的HBase亂碼問題怎么解決

到這里我們可以知道原因了:由于集群中兩臺機器的 jvm 參數(file.encoding)不一致導致了部分中文結果的亂碼。

3、解決方案:

知道原因了,那就看如何解決了,目的就是要改變 file.encoding 的值 。

(1)永久方案:

由于這個參數是 jvm 的啟動參數,運行時不可被更改(你可以理解為這個參數是個全局參數,而且被緩存了,如果一旦運行時更改了, 可能會造成整個 jvm 里面的程序奔潰),你只能修改系統的charset, 或者jvm的啟動參數里加上 -Dfile.encoding="UTF-8">,你運行時 setProperty("file.encoding","ISO-8859-1"); 這樣是沒用的,so,永久的解決辦法是:啥時候把這兩臺機器offline 改編碼后再online,然后再手動執行下 data balance。

或者可以在提交作業的時候設置作業參數: –Dmapred.child.env="LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8"

(2)臨時工方案:

不想這么大動干戈,想要臨時解決方案,也行,那就需要在咱們自己的業務代碼里繞開 jvm 提供的默認 file.encoding 編碼,自己指定編碼:

BufferedReader in = new BufferedReader(new FileReader(path.toString()));
換成:
BufferedReader in = new BufferedReader((new InputStreamReader(new FileInputStream(path.toString()),"utf-8")));

上面一句是我之前亂碼的代碼,如果你沒有指定讀取編碼,那么 jvm 會使用自己的 file.encoding,這樣就會造成在某些機器上讀取文件就亂掉了。下面一句是自己指定編碼,這樣繞開了 jvm 的默認編碼,與 jvm 從此形同陌路~ 

PS:FileReader 貌似沒有提供指定編碼的構造方法,所以換成了下面的類。

(3)疑問:

為什么之前一直都沒亂碼,而這次讀文件卻亂碼了呢?

那是因為 hbase 的 Bytes、map 的 fileinputformat key/value、mapreduce 的 context.write 默認都是自己硬編碼了 utf-8,做到了 和 jvm 編碼無關,所以不會遇到上述問題。

4、深入理解 jvm 的 -Dfile.encoding 參數

上面說了這么多,可能有同學還是不大明白:jvm 的這參數有毛用啊?為毛之前都沒聽過這玩意呢?

恩,沒聽過正常,之前我也沒聽過哈~

從源碼開始追蹤

在JDK 1.6.0_20的src.zip文件中,查找包含file.encoding字眼的文件.
共找到4個, 分別是:
(a)先上重頭戲 java.nio.Charset類:

public static Charset defaultCharset() {
		if (defaultCharset == null) {
			synchronized (Charset.class) {
				java.security.PrivilegedAction pa = new GetPropertyAction("file.encoding");
				String csn = (String) AccessController.doPrivileged(pa);
				Charset cs = lookup(csn);
				if (cs != null)
					defaultCharset = cs;
				else
					defaultCharset = forName("UTF-8");
			}
		}
		return defaultCharset;
	}

在java中,如果沒有指定charset的時候,比如new String(byte[] bytes), 都會調用Charset.defaultCharset()的方法,我們可以清楚的看到defaultCharset是只能被初始化一次,這里還是有點小問題的,在多線程并發調用的時候還是會初始話多次,當然后面都是從cache(lookup的函數)里讀出來的,問題也不大。
當我們在改變System.getProperties里的file.encoding 的時候,defaultCharset已經被初始化過了,所以不會在調用初始化的代碼。
當jvm 啟動的時候,load class, 最后調用main函數之前,defaultCharset已經初始化好,而很多函數里都掉用了這個方法象String.getBytes, 還有 InputStreamReader, InputStreamWriter 都是調用了 Charset.defaultCharset()的方法。

(b)java.net.URLEncoder的靜態構造方法,  影響到的方法 java.net.URLEncoder.encode(String)

恩,這里也需要注意,之前已經有同學掉坑里去了,請使用:encode(String s, String enc) 方法,此法無側漏,一覺睡到大天亮~

(c)com.sun.org.apache.xml.internal.serializer.Encoding的getMimeEncoding方法(209行起)

(d)最后一個javax.print.DocFlavor類的靜態構造方法

可以看到,系統變量file.encoding影響到
1. Charset.defaultCharset() Java環境中最關鍵的編碼設置
2. URLEncoder.encode(String) Web環境中最常遇到的編碼使用
3. com.sun.org.apache.xml.internal.serializer.Encoding 影響對無編碼設置的xml文件的讀取
4. javax.print.DocFlavor 影響打印的編碼

到此,關于“jvm file.encoding屬性引起的HBase亂碼問題怎么解決”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

巴中市| 黑水县| 常德市| 湘阴县| 东乌珠穆沁旗| 沅江市| 荔浦县| 聂拉木县| 保定市| 特克斯县| 临沭县| 宁国市| 黑龙江省| 清涧县| 津市市| 阜康市| 鄄城县| 华蓥市| 东港市| 濮阳市| 青神县| 环江| 奉贤区| 鹤峰县| 保山市| 定西市| 偏关县| 阿拉善右旗| 永仁县| 韶关市| 扶绥县| 蕉岭县| 乌拉特前旗| 辉南县| 垫江县| 晋江市| 贡觉县| 潜山县| 民丰县| 汉川市| 临漳县|