The important thing in life is to have a great aim , and the determination

          常用鏈接

          統(tǒng)計(jì)

          IT技術(shù)鏈接

          保險(xiǎn)相關(guān)

          友情鏈接

          基金知識(shí)

          生活相關(guān)

          最新評(píng)論

          2017年4月29日 #

          POI操作Excel

          一、POI概述   Apache POI是Apache軟件基金會(huì)的開(kāi)放源碼函式庫(kù),POI提供API給Java程序?qū)icrosoft Office格式檔案讀和寫(xiě)的功能。   結(jié)構(gòu): HSSF - 提供讀寫(xiě)Microsoft Excel格式檔案的功能。 XSSF - 提供讀寫(xiě)Microsoft Excel OOXML格式檔案的功能。 HWPF - 提供讀寫(xiě)Microsoft Word格式檔案的功能。 HSLF - 提供讀寫(xiě)Microsoft PowerPoint格式檔案的功能。 HDGF - 提供讀寫(xiě)Microsoft Visio格式檔案的功能。  使用必須引入依賴(lài) org.apache.poi poi 3.17 注:3.17版本是支持jdk6的最后版本 二、HSSF概況   HSSF 是Horrible SpreadSheet Format的縮寫(xiě),通過(guò)HSSF,你可以用純Java代碼來(lái)讀取、寫(xiě)入、修改Excel文件。HSSF 為讀取操作提供了兩類(lèi)API:usermodel和eventusermodel,即“用戶(hù)模型”和“事件-用戶(hù)模型”。 三、 POI EXCEL文檔結(jié)構(gòu)類(lèi) HSSFWorkbook excel文檔對(duì)象 HSSFSheet excel的sheet HSSFRow excel的行 HSSFCell excel的單元格 HSSFFont excel字體 HSSFName 名稱(chēng) HSSFDataFormat 日期格式 HSSFHeader sheet頭 HSSFFooter sheet尾 HSSFCellStyle cell樣式 HSSFDateUtil 日期 HSSFPrintSetup 打印 HSSFErrorConstants 錯(cuò)誤信息表 四、EXCEL的讀寫(xiě)操作 1、讀取“區(qū)域數(shù)據(jù).xls”并儲(chǔ)存于list集合中,“區(qū)域數(shù)據(jù).xls”如下圖 public List importXLS(){ ArrayList list = new ArrayList<>(); try {      //1、獲取文件輸入流      InputStream inputStream = new FileInputStream("/Users/Shared/區(qū)域數(shù)據(jù).xls");      //2、獲取Excel工作簿對(duì)象 HSSFWorkbook workbook = new HSSFWorkbook(inputStream);      //3、得到Excel工作表對(duì)象 HSSFSheet sheetAt = workbook.getSheetAt(0); //4、循環(huán)讀取表格數(shù)據(jù)      for (Row row : sheetAt) {        //首行(即表頭)不讀取 if (row.getRowNum() == 0) { continue; } //讀取當(dāng)前行中單元格數(shù)據(jù),索引從0開(kāi)始        String areaNum = row.getCell(0).getStringCellValue(); String province = row.getCell(1).getStringCellValue(); String city = row.getCell(2).getStringCellValue(); String district = row.getCell(3).getStringCellValue(); String postcode = row.getCell(4).getStringCellValue(); Area area = new Area(); area.setCity(city); area.setDistrict(district); area.setProvince(province);        area.setPostCode(postcode); list.add(area); }      //5、關(guān)閉流 workbook.close(); } catch (IOException e) { e.printStackTrace(); }   return list; } 2、導(dǎo)出數(shù)據(jù)到“區(qū)域數(shù)據(jù).xls”文件中,頁(yè)面數(shù)據(jù)如下圖: public void exportExcel() throws IOException { Page page = areaService.pageQuery(null); List list = page.getContent(); //1.在內(nèi)存中創(chuàng)建一個(gè)excel文件 HSSFWorkbook hssfWorkbook = new HSSFWorkbook(); //2.創(chuàng)建工作簿 HSSFSheet sheet = hssfWorkbook.createSheet(); //3.創(chuàng)建標(biāo)題行 HSSFRow titlerRow = sheet.createRow(0); titlerRow.createCell(0).setCellValue("省"); titlerRow.createCell(1).setCellValue("市"); titlerRow.createCell(2).setCellValue("區(qū)"); titlerRow.createCell(3).setCellValue("郵編"); titlerRow.createCell(4).setCellValue("簡(jiǎn)碼"); titlerRow.createCell(5).setCellValue("城市編碼"); //4.遍歷數(shù)據(jù),創(chuàng)建數(shù)據(jù)行 for (Area area : list) { //獲取最后一行的行號(hào) int lastRowNum = sheet.getLastRowNum(); HSSFRow dataRow = sheet.createRow(lastRowNum + 1); dataRow.createCell(0).setCellValue(area.getProvince()); dataRow.createCell(1).setCellValue(area.getCity()); dataRow.createCell(2).setCellValue(area.getDistrict()); dataRow.createCell(3).setCellValue(area.getPostcode()); dataRow.createCell(4).setCellValue(area.getShortcode()); dataRow.createCell(5).setCellValue(area.getCitycode()); } //5.創(chuàng)建文件名 String fileName = "區(qū)域數(shù)據(jù)統(tǒng)計(jì).xls"; //6.獲取輸出流對(duì)象 HttpServletResponse response = ServletActionContext.getResponse(); ServletOutputStream outputStream = response.getOutputStream(); //7.獲取mimeType ServletContext servletContext = ServletActionContext.getServletContext(); String mimeType = servletContext.getMimeType(fileName); //8.獲取瀏覽器信息,對(duì)文件名進(jìn)行重新編碼 HttpServletRequest request = ServletActionContext.getRequest(); fileName = FileUtils.filenameEncoding(fileName, request); //9.設(shè)置信息頭 response.setContentType(mimeType); response.setHeader("Content-Disposition","attachment;filename="+fileName); //10.寫(xiě)出文件,關(guān)閉流 hssfWorkbook.write(outputStream); hssfWorkbook.close(); } 工具類(lèi) public class FileUtils { public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException { String agent = request.getHeader("User-Agent"); //獲取瀏覽器 if (agent.contains("Firefox")) { BASE64Encoder base64Encoder = new BASE64Encoder(); filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; } else if(agent.contains("MSIE")) { filename = URLEncoder.encode(filename, "utf-8"); } else if(agent.contains ("Safari")) { filename = new String (filename.getBytes ("utf-8"),"ISO8859-1"); } else { filename = URLEncoder.encode(filename, "utf-8"); } return filename; } } 寫(xiě)出xls文件: 五、 EXCEL常用操作方法 1、 得到Excel常用對(duì)象 POIFSFileSystem fs=newPOIFSFileSystem(new FileInputStream("d:/test.xls")); //得到Excel工作簿對(duì)象 HSSFWorkbook wb = new HSSFWorkbook(fs); //得到Excel工作表對(duì)象 HSSFSheet sheet = wb.getSheetAt(0); //得到Excel工作表的行 HSSFRow row = sheet.getRow(i); //得到Excel工作表指定行的單元格 HSSFCell cell = row.getCell((short) j); cellStyle = cell.getCellStyle();//得到單元格樣式 2、建立Excel常用對(duì)象 HSSFWorkbook wb = new HSSFWorkbook();//創(chuàng)建Excel工作簿對(duì)象 HSSFSheet sheet = wb.createSheet("new sheet");//創(chuàng)建Excel工作表對(duì)象 HSSFRow row = sheet.createRow((short)0); //創(chuàng)建Excel工作表的行 cellStyle = wb.createCellStyle();//創(chuàng)建單元格樣式 row.createCell((short)0).setCellStyle(cellStyle); //創(chuàng)建Excel工作表指定行的單元格 row.createCell((short)0).setCellValue(1); //設(shè)置Excel工作表的值 3、設(shè)置sheet名稱(chēng)和單元格內(nèi)容 wb.setSheetName(1, "第一張工作表",HSSFCell.ENCODING_UTF_16); cell.setEncoding((short) 1); cell.setCellValue("單元格內(nèi)容"); 4、取得sheet的數(shù)目 wb.getNumberOfSheets() 5、 根據(jù)index取得sheet對(duì)象 HSSFSheet sheet = wb.getSheetAt(0); 6、取得有效的行數(shù) int rowcount = sheet.getLastRowNum(); 7、取得一行的有效單元格個(gè)數(shù) row.getLastCellNum(); 8、單元格值類(lèi)型讀寫(xiě) cell.setCellType(HSSFCell.CELL_TYPE_STRING); //設(shè)置單元格為STRING類(lèi)型 cell.getNumericCellValue();//讀取為數(shù)值類(lèi)型的單元格內(nèi)容 9、設(shè)置列寬、行高 sheet.setColumnWidth((short)column,(short)width); row.setHeight((short)height); 10、添加區(qū)域,合并單元格 Region region = new Region((short)rowFrom,(short)columnFrom,(short)rowTo ,(short)columnTo);//合并從第rowFrom行columnFrom列 sheet.addMergedRegion(region);// 到rowTo行columnTo的區(qū)域 //得到所有區(qū)域 sheet.getNumMergedRegions() 11、保存Excel文件 FileOutputStream fileOut = new FileOutputStream(path); wb.write(fileOut); 12、根據(jù)單元格不同屬性返回字符串?dāng)?shù)值 public String getCellStringValue(HSSFCell cell) {   String cellValue = "";   switch (cell.getCellType()) {     case HSSFCell.CELL_TYPE_STRING://字符串類(lèi)型         cellValue = cell.getStringCellValue();         if(cellValue.trim().equals("")||cellValue.trim().length()<=0)           cellValue=" ";         break;     case HSSFCell.CELL_TYPE_NUMERIC: //數(shù)值類(lèi)型         cellValue = String.valueOf(cell.getNumericCellValue());         break;     case HSSFCell.CELL_TYPE_FORMULA: //公式         cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);         cellValue = String.valueOf(cell.getNumericCellValue());         break;     case HSSFCell.CELL_TYPE_BLANK:         cellValue=" ";         break;     case HSSFCell.CELL_TYPE_BOOLEAN:         break;     case HSSFCell.CELL_TYPE_ERROR:         break;     default:         break;   }   return cellValue; } 13、常用單元格邊框格式 HSSFCellStyle style = wb.createCellStyle(); style.setBorderBottom(HSSFCellStyle.BORDER_DOTTED);//下邊框 style.setBorderLeft(HSSFCellStyle.BORDER_DOTTED);//左邊框 style.setBorderRight(HSSFCellStyle.BORDER_THIN);//右邊框 style.setBorderTop(HSSFCellStyle.BORDER_THIN);//上邊框 14、設(shè)置字體和內(nèi)容位置 HSSFFont f = wb.createFont(); f.setFontHeightInPoints((short) 11);//字號(hào) f.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);//加粗 style.setFont(f); style.setAlignment(HSSFCellStyle.ALIGN_CENTER);//左右居中 style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);//上下居中 style.setRotation(short rotation);//單元格內(nèi)容的旋轉(zhuǎn)的角度 HSSFDataFormat df = wb.createDataFormat(); style1.setDataFormat(df.getFormat("0.00%"));//設(shè)置單元格數(shù)據(jù)格式 cell.setCellFormula(string);//給單元格設(shè)公式 style.setRotation(short rotation);//單元格內(nèi)容的旋轉(zhuǎn)的角度 15、插入圖片 //先把讀進(jìn)來(lái)的圖片放到一個(gè)ByteArrayOutputStream中,以便產(chǎn)生ByteArray ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); BufferedImage bufferImg = ImageIO.read(new File("ok.jpg")); ImageIO.write(bufferImg,"jpg",byteArrayOut); //讀進(jìn)一個(gè)excel模版 FileInputStream fos = new FileInputStream(filePathName+"/stencil.xlt"); fs = new POIFSFileSystem(fos); //創(chuàng)建一個(gè)工作薄 HSSFWorkbook wb = new HSSFWorkbook(fs); HSSFSheet sheet = wb.getSheetAt(0); HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); HSSFClientAnchor anchor = new HSSFClientAnchor(0,0,1023,255,(short) 0,0,(short)10,10); patriarch.createPicture(anchor , wb.addPicture(byteArrayOut.toByteArray(),HSSFWorkbook.PICTURE_TYPE_JPEG)); 16、調(diào)整工作表位置 HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet("format sheet"); HSSFPrintSetup ps = sheet.getPrintSetup(); sheet.setAutobreaks(true); ps.setFitHeight((short)1); ps.setFitWidth((short)1);

          posted @ 2020-03-20 10:13 鴻雁 閱讀(120) | 評(píng)論 (0)編輯 收藏

          python操作文件存在的問(wèn)題解決辦法

          1、在學(xué)習(xí)從文件讀取數(shù)據(jù)中,寫(xiě)了個(gè)示例代碼,讀取不在同一個(gè)目錄的file.txt,運(yùn)行后報(bào)這個(gè)Python OSError: [Errno 22] Invalid argument:錯(cuò)誤: (1)、首先,在F盤(pán)的python_stu中新增了一個(gè)file.txt,同時(shí)在F盤(pán)的python_stu文件目錄底下新增一個(gè)file文件夾,里面有個(gè)file_reader.py來(lái)讀取python_stu文件目錄底下的file.txt,代碼分別如下: file.txt: 測(cè)試 測(cè)試2 測(cè)試3 file_reader.py: with open('F:\python_stu\file.txt') as file_obj: contents = file_obj.read(); print(contents.rstrip()); (2)、運(yùn)行后報(bào)錯(cuò): (3)、出現(xiàn)這種錯(cuò)誤的原因是由于讀取不到這個(gè)文件,看Traceback報(bào)的錯(cuò)誤,最后一行,很明顯讀取不到file.txt,前面的F:\\python_stu沒(méi)錯(cuò),后面的名稱(chēng)怎么變了,還是x0cile.txt。 (4)、解決辦法,可修改上述第一行代碼為: with open('F:\python_stu/file.txt') as file_obj: 或者: with open('F:/python_stu/file.txt') as file_obj: 或者: with open('F://python_stu//file.txt') as file_obj: 又或者: with open('F:\\python_stu\\file.txt') as file_obj: 還有一些我就不附上了,上面第一種方式不統(tǒng)一,最好不要用,用統(tǒng)一的方式,而且有時(shí)候還有注意一些轉(zhuǎn)義字符,比如 \t,\n也會(huì)導(dǎo)致報(bào)錯(cuò)。

          posted @ 2019-05-14 23:04 鴻雁 閱讀(162) | 評(píng)論 (0)編輯 收藏

          Hadoop-2.4.1學(xué)習(xí)之QJM HA的自動(dòng)故障轉(zhuǎn)移

          前面學(xué)習(xí)了使用命令hdfs haadmin -failover手動(dòng)進(jìn)行故障轉(zhuǎn)移,在該模式下,即使現(xiàn)役NameNode已經(jīng)失效,系統(tǒng)也不會(huì)自動(dòng)從現(xiàn)役NameNode轉(zhuǎn)移到待機(jī)NameNode,下面學(xué)習(xí)如何配置部署HA自動(dòng)進(jìn)行故障轉(zhuǎn)移。自動(dòng)故障轉(zhuǎn)移為HDFS部署增加了兩個(gè)新組件:ZooKeeper和ZKFailoverController(ZKFC)進(jìn)程。ZooKeeper是維護(hù)少量協(xié)調(diào)數(shù)據(jù),通知客戶(hù)端這些數(shù)據(jù)的改變和監(jiān)視客戶(hù)端故障的高可用服務(wù)。HA的自動(dòng)故障轉(zhuǎn)移依賴(lài)于ZooKeeper的以下功能:

          • 故障檢測(cè):集群中的每個(gè)NameNode在ZooKeeper中維護(hù)了一個(gè)持久會(huì)話(huà),如果機(jī)器崩潰,ZooKeeper中的會(huì)話(huà)將終止,ZooKeeper通知另一個(gè)NameNode需要觸發(fā)故障轉(zhuǎn)移。
          • 現(xiàn)役NameNode選擇:ZooKeeper提供了一個(gè)簡(jiǎn)單的機(jī)制用于唯一的選擇一個(gè)節(jié)點(diǎn)為active狀態(tài)。如果目前現(xiàn)役NameNode崩潰,另一個(gè)節(jié)點(diǎn)可能從ZooKeeper獲得特殊的排外鎖以表明它應(yīng)該成為現(xiàn)役NameNode。

                 ZKFC是自動(dòng)故障轉(zhuǎn)移中的另一個(gè)新組件,是ZooKeeper的客戶(hù)端,也監(jiān)視和管理NameNode的狀態(tài)。每個(gè)運(yùn)行NameNode的主機(jī)也運(yùn)行了一個(gè)ZKFC進(jìn)程,ZKFC負(fù)責(zé):

          • 健康監(jiān)測(cè):ZKFC使用一個(gè)健康檢查命令定期地ping與之在相同主機(jī)的NameNode,只要該NameNode及時(shí)地回復(fù)健康狀態(tài),ZKFC認(rèn)為該節(jié)點(diǎn)是健康的。如果該節(jié)點(diǎn)崩潰,凍結(jié)或進(jìn)入不健康狀態(tài),健康監(jiān)測(cè)器標(biāo)識(shí)該節(jié)點(diǎn)為非健康的。
          • ZooKeeper會(huì)話(huà)管理:當(dāng)本地NameNode是健康的,ZKFC保持一個(gè)在ZooKeeper中打開(kāi)的會(huì)話(huà)。如果本地NameNode處于active狀態(tài),ZKFC也保持一個(gè)特殊的znode鎖,該鎖使用了ZooKeeper對(duì)短暫節(jié)點(diǎn)的支持,如果會(huì)話(huà)終止,鎖節(jié)點(diǎn)將自動(dòng)刪除。
          • 基于ZooKeeper的選擇:如果本地NameNode是健康的,且ZKFC發(fā)現(xiàn)沒(méi)有其它的節(jié)點(diǎn)當(dāng)前持有znode鎖,它將為自己獲取該鎖。如果成功,則它已經(jīng)贏得了選擇,并負(fù)責(zé)運(yùn)行故障轉(zhuǎn)移進(jìn)程以使它的本地NameNode為active。故障轉(zhuǎn)移進(jìn)城與前面描述的手動(dòng)故障轉(zhuǎn)移相似,首先如果必要保護(hù)之前的現(xiàn)役NameNode,然后本地NameNode轉(zhuǎn)換為active狀態(tài)。

                 在典型部署中,ZooKeeper守護(hù)進(jìn)程運(yùn)行在三個(gè)或者五個(gè)節(jié)點(diǎn)上,但由于ZooKeeper本身需要較少的資源,所以將ZooKeeper部署在與現(xiàn)役NameNode和待機(jī)NameNode相同的主機(jī)上,還可以將ZooKeeper部署到與YARN的ResourceManager相同的節(jié)點(diǎn)上。建議配置ZooKeeper將數(shù)據(jù)存儲(chǔ)在與HDFS元數(shù)據(jù)不同的硬盤(pán)上以得到最好的性能和隔離性。在配置自動(dòng)故障轉(zhuǎn)移之前需要先停掉集群,目前在集群運(yùn)行時(shí)還不可能將手動(dòng)故障轉(zhuǎn)移的安裝轉(zhuǎn)換為自動(dòng)故障轉(zhuǎn)移的安裝。接下來(lái)看看如何配置HA的自動(dòng)故障轉(zhuǎn)移。首先在hdfs-site.xml中添加下面的參數(shù),該參數(shù)的值默認(rèn)為false:

          1. <property>  
          2.    <name>dfs.ha.automatic-failover.enabled</name>  
          3.    <value>true</value>  
          4. </property>  

                 在core-site.xml文件中添加下面的參數(shù),該參數(shù)的值為ZooKeeper服務(wù)器的地址,ZKFC將使用該地址。

          1. <property>  
          2.    <name>ha.zookeeper.quorum</name> <value>zk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181</value>  
          3. </property>  

                 在HA或者HDFS聯(lián)盟中,上面的兩個(gè)參數(shù)還需要以NameServiceID為后綴,比如dfs.ha.automatic-failover.enabled.mycluster。除了上面的兩個(gè)參數(shù)外,還有其它幾個(gè)參數(shù)用于自動(dòng)故障轉(zhuǎn)移,比如ha.zookeeper.session-timeout.ms,但對(duì)于大多數(shù)安裝來(lái)說(shuō)都不是必須的。

                 在添加了上述的配置參數(shù)后,下一步就是在ZooKeeper中初始化要求的狀態(tài),可以在任一NameNode中運(yùn)行下面的命令實(shí)現(xiàn)該目的,該命令將在ZooKeeper中創(chuàng)建znode:

          1. $ hdfs zkfc -formatZK  

                 在啟用自動(dòng)故障轉(zhuǎn)移的集群中,start-dfs.sh腳本將在任何運(yùn)行NameNode的主機(jī)上自動(dòng)啟動(dòng)ZKFC守護(hù)進(jìn)程,一旦ZKFC啟動(dòng)完畢,它們將自動(dòng)選擇一個(gè)NameNode為現(xiàn)役NameNode。如果手動(dòng)管理集群中的服務(wù),需要在每臺(tái)運(yùn)行NameNode的主機(jī)上手動(dòng)啟動(dòng)ZKFC,命令為:

          1. hadoop-daemon.sh start zkfc  
          2. hdfs zkfc  

                 如果正在運(yùn)行一個(gè)安全的集群,可能想確保存儲(chǔ)在ZooKeeper中的信息也是安全的,這將阻止惡意的客戶(hù)端修改ZooKeeper中的元數(shù)據(jù)或者潛在地觸發(fā)一個(gè)錯(cuò)誤的故障轉(zhuǎn)移。為了保護(hù)ZooKeeper中的信息,首先在core-site.xml中添加下面的參數(shù):

          1. <property>  
          2.    <name>ha.zookeeper.auth</name>  
          3.    <value>@/path/to/zk-auth.txt</value>  
          4.  </property>  
          5.  <property>  
          6.    <name>ha.zookeeper.acl</name>  
          7.    <value>@/path/to/zk-acl.txt</value>  
          8.  </property>  

                 參數(shù)值中的@字符表示參數(shù)值保存在@后的硬盤(pán)文件中。第一個(gè)配置文件指定了ZooKeeper的認(rèn)證列表,其格式與ZK CLI使用的相同,例如:digest:hdfs-zkfcs:mypassword,其中hdfs-zkfcs為ZooKeeper的用戶(hù)名,mypassword為密碼。其次使用下面的命令為該認(rèn)證生成一個(gè)ZooKeeper訪(fǎng)問(wèn)控制列表:

          1. $ java -cp $ZK_HOME/lib/*:$ZK_HOME/zookeeper-3.4.2.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider hdfs-zkfcs:mypassword  
          2. output: hdfs-zkfcs:mypassword->hdfs-zkfcs:P/OQvnYyU/nF/mGYvB/xurX8dYs=   

                 拷貝->之后的字符串并添加digest:前綴,然后粘貼到zk-acls.txt中,例如:digest:hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=:rwcda。要想使ACLs生效,需要再次運(yùn)行zkfc –formatZK。最后可能像下面這樣在ZK CLI中驗(yàn)證ACLs:

          1. [zk: localhost:2181(CONNECTED) 1] getAcl /hadoop-ha  
          2. 'digest,'hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=  
          3. : cdrwa  

                 在安裝完成自動(dòng)故障轉(zhuǎn)移后,或許需要測(cè)試一下。首先定位現(xiàn)役NameNode,可以通過(guò)訪(fǎng)問(wèn)NameNode的web頁(yè)面來(lái)確定哪個(gè)NameNode是active狀態(tài)的。一旦確定了處于active狀態(tài)的NameNode,就需要在該節(jié)點(diǎn)上制造點(diǎn)故障,比如使用命令kill -9 <pid of NN>模擬JVM崩潰,或重啟主機(jī)或拔掉網(wǎng)線(xiàn)來(lái)模擬不同的中斷。一旦觸發(fā)了自動(dòng)故障轉(zhuǎn)移,另一個(gè)NameNode應(yīng)該自動(dòng)在幾秒鐘內(nèi)變?yōu)閍ctive狀態(tài)。檢測(cè)到故障并觸發(fā)故障轉(zhuǎn)移由參數(shù)ha.zookeeper.session-timeout.ms控制,該參數(shù)為與core-site.xml中,默認(rèn)為5秒。如果測(cè)試不成功,可能是配置問(wèn)題,檢查ZKFC和NameNode進(jìn)程的日志以進(jìn)一步診斷問(wèn)題,通常錯(cuò)誤都是很明顯的。

          posted @ 2017-08-13 18:49 鴻雁 閱讀(434) | 評(píng)論 (0)編輯 收藏

          Yarn 調(diào)度器Scheduler詳解

          理想情況下,我們應(yīng)用對(duì)Yarn資源的請(qǐng)求應(yīng)該立刻得到滿(mǎn)足,但現(xiàn)實(shí)情況資源往往是有限的,特別是在一個(gè)很繁忙的集群,一個(gè)應(yīng)用資源的請(qǐng)求經(jīng)常需要等待一段時(shí)間才能的到相應(yīng)的資源。在Yarn中,負(fù)責(zé)給應(yīng)用分配資源的就是Scheduler。其實(shí)調(diào)度本身就是一個(gè)難題,很難找到一個(gè)完美的策略可以解決所有的應(yīng)用場(chǎng)景。為此,Yarn提供了多種調(diào)度器和可配置的策略供我們選擇。

          一、調(diào)度器的選擇

          在Yarn中有三種調(diào)度器可以選擇:FIFO Scheduler ,Capacity SchedulerFairS cheduler

          FIFO Scheduler把應(yīng)用按提交的順序排成一個(gè)隊(duì)列,這是一個(gè)先進(jìn)先出隊(duì)列,在進(jìn)行資源分配的時(shí)候,先給隊(duì)列中最頭上的應(yīng)用進(jìn)行分配資源,待最頭上的應(yīng)用需求滿(mǎn)足后再給下一個(gè)分配,以此類(lèi)推。

          FIFO Scheduler是最簡(jiǎn)單也是最容易理解的調(diào)度器,也不需要任何配置,但它并不適用于共享集群。大的應(yīng)用可能會(huì)占用所有集群資源,這就導(dǎo)致其它應(yīng)用被阻塞。在共享集群中,更適合采用Capacity SchedulerFair Scheduler,這兩個(gè)調(diào)度器都允許大任務(wù)和小任務(wù)在提交的同時(shí)獲得一定的系統(tǒng)資源。

          下面“Yarn調(diào)度器對(duì)比圖”展示了這幾個(gè)調(diào)度器的區(qū)別,從圖中可以看出,在FIFO 調(diào)度器中,小任務(wù)會(huì)被大任務(wù)阻塞。

          而對(duì)于Capacity調(diào)度器,有一個(gè)專(zhuān)門(mén)的隊(duì)列用來(lái)運(yùn)行小任務(wù),但是為小任務(wù)專(zhuān)門(mén)設(shè)置一個(gè)隊(duì)列會(huì)預(yù)先占用一定的集群資源,這就導(dǎo)致大任務(wù)的執(zhí)行時(shí)間會(huì)落后于使用FIFO調(diào)度器時(shí)的時(shí)間。

          在Fair調(diào)度器中,我們不需要預(yù)先占用一定的系統(tǒng)資源,F(xiàn)air調(diào)度器會(huì)為所有運(yùn)行的job動(dòng)態(tài)的調(diào)整系統(tǒng)資源。如下圖所示,當(dāng)?shù)谝粋€(gè)大job提交時(shí),只有這一個(gè)job在運(yùn)行,此時(shí)它獲得了所有集群資源;當(dāng)?shù)诙€(gè)小任務(wù)提交后,F(xiàn)air調(diào)度器會(huì)分配一半資源給這個(gè)小任務(wù),讓這兩個(gè)任務(wù)公平的共享集群資源。

          需要注意的是,在下圖Fair調(diào)度器中,從第二個(gè)任務(wù)提交到獲得資源會(huì)有一定的延遲,因?yàn)樗枰却谝粋€(gè)任務(wù)釋放占用的Container。小任務(wù)執(zhí)行完成之后也會(huì)釋放自己占用的資源,大任務(wù)又獲得了全部的系統(tǒng)資源。最終的效果就是Fair調(diào)度器即得到了高的資源利用率又能保證小任務(wù)及時(shí)完成。

          Yarn調(diào)度器對(duì)比圖: 
          技術(shù)分享

          二、Capacity Scheduler(容器調(diào)度器)的配置

          2.1 容器調(diào)度介紹

          Capacity 調(diào)度器允許多個(gè)組織共享整個(gè)集群,每個(gè)組織可以獲得集群的一部分計(jì)算能力。通過(guò)為每個(gè)組織分配專(zhuān)門(mén)的隊(duì)列,然后再為每個(gè)隊(duì)列分配一定的集群資源,這樣整個(gè)集群就可以通過(guò)設(shè)置多個(gè)隊(duì)列的方式給多個(gè)組織提供服務(wù)了。除此之外,隊(duì)列內(nèi)部又可以垂直劃分,這樣一個(gè)組織內(nèi)部的多個(gè)成員就可以共享這個(gè)隊(duì)列資源了,在一個(gè)隊(duì)列內(nèi)部,資源的調(diào)度是采用的是先進(jìn)先出(FIFO)策略。

          通過(guò)上面那幅圖,我們已經(jīng)知道一個(gè)job可能使用不了整個(gè)隊(duì)列的資源。然而如果這個(gè)隊(duì)列中運(yùn)行多個(gè)job,如果這個(gè)隊(duì)列的資源夠用,那么就分配給這些job,如果這個(gè)隊(duì)列的資源不夠用了呢?其實(shí)Capacity調(diào)度器仍可能分配額外的資源給這個(gè)隊(duì)列,這就是“彈性隊(duì)列”(queue elasticity)的概念。

          在正常的操作中,Capacity調(diào)度器不會(huì)強(qiáng)制釋放Container,當(dāng)一個(gè)隊(duì)列資源不夠用時(shí),這個(gè)隊(duì)列只能獲得其它隊(duì)列釋放后的Container資源。當(dāng)然,我們可以為隊(duì)列設(shè)置一個(gè)最大資源使用量,以免這個(gè)隊(duì)列過(guò)多的占用空閑資源,導(dǎo)致其它隊(duì)列無(wú)法使用這些空閑資源,這就是”彈性隊(duì)列”需要權(quán)衡的地方。

          2.2 容器調(diào)度的配置

          假設(shè)我們有如下層次的隊(duì)列:

          root ├── prod └── dev     ├── eng     └── science 

          下面是一個(gè)簡(jiǎn)單的Capacity調(diào)度器的配置文件,文件名為capacity-scheduler.xml。在這個(gè)配置中,在root隊(duì)列下面定義了兩個(gè)子隊(duì)列proddev,分別占40%和60%的容量。需要注意,一個(gè)隊(duì)列的配置是通過(guò)屬性yarn.sheduler.capacity.<queue-path>.<sub-property>指定的,<queue-path>代表的是隊(duì)列的繼承樹(shù),如root.prod隊(duì)列,<sub-property>一般指capacitymaximum-capacity

          技術(shù)分享

          我們可以看到,dev隊(duì)列又被分成了engscience兩個(gè)相同容量的子隊(duì)列。devmaximum-capacity屬性被設(shè)置成了75%,所以即使prod隊(duì)列完全空閑dev也不會(huì)占用全部集群資源,也就是說(shuō),prod隊(duì)列仍有25%的可用資源用來(lái)應(yīng)急。我們注意到,engscience兩個(gè)隊(duì)列沒(méi)有設(shè)置maximum-capacity屬性,也就是說(shuō)engscience隊(duì)列中的job可能會(huì)用到整個(gè)dev隊(duì)列的所有資源(最多為集群的75%)。而類(lèi)似的,prod由于沒(méi)有設(shè)置maximum-capacity屬性,它有可能會(huì)占用集群全部資源。

          Capacity容器除了可以配置隊(duì)列及其容量外,我們還可以配置一個(gè)用戶(hù)或應(yīng)用可以分配的最大資源數(shù)量、可以同時(shí)運(yùn)行多少應(yīng)用、隊(duì)列的ACL認(rèn)證等。

          2.3 隊(duì)列的設(shè)置

          關(guān)于隊(duì)列的設(shè)置,這取決于我們具體的應(yīng)用。比如,在MapReduce中,我們可以通過(guò)mapreduce.job.queuename屬性指定要用的隊(duì)列。如果隊(duì)列不存在,我們?cè)谔峤蝗蝿?wù)時(shí)就會(huì)收到錯(cuò)誤。如果我們沒(méi)有定義任何隊(duì)列,所有的應(yīng)用將會(huì)放在一個(gè)default隊(duì)列中。

          注意:對(duì)于Capacity調(diào)度器,我們的隊(duì)列名必須是隊(duì)列樹(shù)中的最后一部分,如果我們使用隊(duì)列樹(shù)則不會(huì)被識(shí)別。比如,在上面配置中,我們使用prodeng作為隊(duì)列名是可以的,但是如果我們用root.dev.eng或者dev.eng是無(wú)效的。

          三、Fair Scheduler(公平調(diào)度器)的配置

          3.1 公平調(diào)度

          Fair調(diào)度器的設(shè)計(jì)目標(biāo)是為所有的應(yīng)用分配公平的資源(對(duì)公平的定義可以通過(guò)參數(shù)來(lái)設(shè)置)。在上面的“Yarn調(diào)度器對(duì)比圖”展示了一個(gè)隊(duì)列中兩個(gè)應(yīng)用的公平調(diào)度;當(dāng)然,公平調(diào)度在也可以在多個(gè)隊(duì)列間工作。舉個(gè)例子,假設(shè)有兩個(gè)用戶(hù)A和B,他們分別擁有一個(gè)隊(duì)列。當(dāng)A啟動(dòng)一個(gè)job而B(niǎo)沒(méi)有任務(wù)時(shí),A會(huì)獲得全部集群資源;當(dāng)B啟動(dòng)一個(gè)job后,A的job會(huì)繼續(xù)運(yùn)行,不過(guò)一會(huì)兒之后兩個(gè)任務(wù)會(huì)各自獲得一半的集群資源。如果此時(shí)B再啟動(dòng)第二個(gè)job并且其它job還在運(yùn)行,則它將會(huì)和B的第一個(gè)job共享B這個(gè)隊(duì)列的資源,也就是B的兩個(gè)job會(huì)用于四分之一的集群資源,而A的job仍然用于集群一半的資源,結(jié)果就是資源最終在兩個(gè)用戶(hù)之間平等的共享。過(guò)程如下圖所示: 
          技術(shù)分享

          3.2 啟用Fair Scheduler

          調(diào)度器的使用是通過(guò)yarn-site.xml配置文件中的yarn.resourcemanager.scheduler.class參數(shù)進(jìn)行配置的,默認(rèn)采用Capacity Scheduler調(diào)度器。如果我們要使用Fair調(diào)度器,需要在這個(gè)參數(shù)上配置FairScheduler類(lèi)的全限定名: org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler

          3.3 隊(duì)列的配置

          Fair調(diào)度器的配置文件位于類(lèi)路徑下的fair-scheduler.xml文件中,這個(gè)路徑可以通過(guò)yarn.scheduler.fair.allocation.file屬性進(jìn)行修改。若沒(méi)有這個(gè)配置文件,F(xiàn)air調(diào)度器采用的分配策略,這個(gè)策略和3.1節(jié)介紹的類(lèi)似:調(diào)度器會(huì)在用戶(hù)提交第一個(gè)應(yīng)用時(shí)為其自動(dòng)創(chuàng)建一個(gè)隊(duì)列,隊(duì)列的名字就是用戶(hù)名,所有的應(yīng)用都會(huì)被分配到相應(yīng)的用戶(hù)隊(duì)列中。

          我們可以在配置文件中配置每一個(gè)隊(duì)列,并且可以像Capacity 調(diào)度器一樣分層次配置隊(duì)列。比如,參考capacity-scheduler.xml來(lái)配置fair-scheduler: 
          技術(shù)分享

          隊(duì)列的層次是通過(guò)嵌套<queue>元素實(shí)現(xiàn)的。所有的隊(duì)列都是root隊(duì)列的孩子,即使我們沒(méi)有配到<root>元素里。在這個(gè)配置中,我們把dev隊(duì)列有分成了engscience兩個(gè)隊(duì)列。

          Fair調(diào)度器中的隊(duì)列有一個(gè)權(quán)重屬性(這個(gè)權(quán)重就是對(duì)公平的定義),并把這個(gè)屬性作為公平調(diào)度的依據(jù)。在這個(gè)例子中,當(dāng)調(diào)度器分配集群40:60資源給proddev時(shí)便視作公平,engscience隊(duì)列沒(méi)有定義權(quán)重,則會(huì)被平均分配。這里的權(quán)重并不是百分比,我們把上面的40和60分別替換成2和3,效果也是一樣的。注意,對(duì)于在沒(méi)有配置文件時(shí)按用戶(hù)自動(dòng)創(chuàng)建的隊(duì)列,它們?nèi)杂袡?quán)重并且權(quán)重值為1。

          每個(gè)隊(duì)列內(nèi)部仍可以有不同的調(diào)度策略。隊(duì)列的默認(rèn)調(diào)度策略可以通過(guò)頂級(jí)元素<defaultQueueSchedulingPolicy>進(jìn)行配置,如果沒(méi)有配置,默認(rèn)采用公平調(diào)度。

          盡管是Fair調(diào)度器,其仍支持在隊(duì)列級(jí)別進(jìn)行FIFO調(diào)度。每個(gè)隊(duì)列的調(diào)度策略可以被其內(nèi)部的<schedulingPolicy> 元素覆蓋,在上面這個(gè)例子中,prod隊(duì)列就被指定采用FIFO進(jìn)行調(diào)度,所以,對(duì)于提交到prod隊(duì)列的任務(wù)就可以按照FIFO規(guī)則順序的執(zhí)行了。需要注意,proddev之間的調(diào)度仍然是公平調(diào)度,同樣engscience也是公平調(diào)度。

          盡管上面的配置中沒(méi)有展示,每個(gè)隊(duì)列仍可配置最大、最小資源占用數(shù)和最大可運(yùn)行的應(yīng)用的數(shù)量。

          3.4 隊(duì)列的設(shè)置

          Fair調(diào)度器采用了一套基于規(guī)則的系統(tǒng)來(lái)確定應(yīng)用應(yīng)該放到哪個(gè)隊(duì)列。在上面的例子中,<queuePlacementPolicy> 元素定義了一個(gè)規(guī)則列表,其中的每個(gè)規(guī)則會(huì)被逐個(gè)嘗試直到匹配成功。例如,上例第一個(gè)規(guī)則specified,則會(huì)把應(yīng)用放到它指定的隊(duì)列中,若這個(gè)應(yīng)用沒(méi)有指定隊(duì)列名或隊(duì)列名不存在,則說(shuō)明不匹配這個(gè)規(guī)則,然后嘗試下一個(gè)規(guī)則。primaryGroup規(guī)則會(huì)嘗試把應(yīng)用放在以用戶(hù)所在的Unix組名命名的隊(duì)列中,如果沒(méi)有這個(gè)隊(duì)列,不創(chuàng)建隊(duì)列轉(zhuǎn)而嘗試下一個(gè)規(guī)則。當(dāng)前面所有規(guī)則不滿(mǎn)足時(shí),則觸發(fā)default規(guī)則,把應(yīng)用放在dev.eng隊(duì)列中。

          當(dāng)然,我們可以不配置queuePlacementPolicy規(guī)則,調(diào)度器則默認(rèn)采用如下規(guī)則:

          <queuePlacementPolicy> <rule name="specified" /> <rule name="user" /> </queuePlacementPolicy> 

          上面規(guī)則可以歸結(jié)成一句話(huà),除非隊(duì)列被準(zhǔn)確的定義,否則會(huì)以用戶(hù)名為隊(duì)列名創(chuàng)建隊(duì)列。

          還有一個(gè)簡(jiǎn)單的配置策略可以使得所有的應(yīng)用放入同一個(gè)隊(duì)列(default),這樣就可以讓所有應(yīng)用之間平等共享集群而不是在用戶(hù)之間。這個(gè)配置的定義如下:

          <queuePlacementPolicy> <rule name="default" /> </queuePlacementPolicy> 

          實(shí)現(xiàn)上面功能我們還可以不使用配置文件,直接設(shè)置yarn.scheduler.fair.user-as-default-queue=false,這樣應(yīng)用便會(huì)被放入default 隊(duì)列,而不是各個(gè)用戶(hù)名隊(duì)列。另外,我們還可以設(shè)置yarn.scheduler.fair.allow-undeclared-pools=false,這樣用戶(hù)就無(wú)法創(chuàng)建隊(duì)列了。

          3.5 搶占(Preemption)

          當(dāng)一個(gè)job提交到一個(gè)繁忙集群中的空隊(duì)列時(shí),job并不會(huì)馬上執(zhí)行,而是阻塞直到正在運(yùn)行的job釋放系統(tǒng)資源。為了使提交job的執(zhí)行時(shí)間更具預(yù)測(cè)性(可以設(shè)置等待的超時(shí)時(shí)間),F(xiàn)air調(diào)度器支持搶占。

          搶占就是允許調(diào)度器殺掉占用超過(guò)其應(yīng)占份額資源隊(duì)列的containers,這些containers資源便可被分配到應(yīng)該享有這些份額資源的隊(duì)列中。需要注意搶占會(huì)降低集群的執(zhí)行效率,因?yàn)楸唤K止的containers需要被重新執(zhí)行。

          可以通過(guò)設(shè)置一個(gè)全局的參數(shù)yarn.scheduler.fair.preemption=true來(lái)啟用搶占功能。此外,還有兩個(gè)參數(shù)用來(lái)控制搶占的過(guò)期時(shí)間(這兩個(gè)參數(shù)默認(rèn)沒(méi)有配置,需要至少配置一個(gè)來(lái)允許搶占Container):

          - minimum share preemption timeout - fair share preemption timeout 

          如果隊(duì)列在minimum share preemption timeout指定的時(shí)間內(nèi)未獲得最小的資源保障,調(diào)度器就會(huì)搶占containers。我們可以通過(guò)配置文件中的頂級(jí)元素<defaultMinSharePreemptionTimeout>為所有隊(duì)列配置這個(gè)超時(shí)時(shí)間;我們還可以在<queue>元素內(nèi)配置<minSharePreemptionTimeout>元素來(lái)為某個(gè)隊(duì)列指定超時(shí)時(shí)間。

          與之類(lèi)似,如果隊(duì)列在fair share preemption timeout指定時(shí)間內(nèi)未獲得平等的資源的一半(這個(gè)比例可以配置),調(diào)度器則會(huì)進(jìn)行搶占containers。這個(gè)超時(shí)時(shí)間可以通過(guò)頂級(jí)元素<defaultFairSharePreemptionTimeout>和元素級(jí)元素<fairSharePreemptionTimeout>分別配置所有隊(duì)列和某個(gè)隊(duì)列的超時(shí)時(shí)間。上面提到的比例可以通過(guò)<defaultFairSharePreemptionThreshold>(配置所有隊(duì)列)和<fairSharePreemptionThreshold>(配置某個(gè)隊(duì)列)進(jìn)行配置,默認(rèn)是0.5。

          posted @ 2017-08-05 00:35 鴻雁 閱讀(366) | 評(píng)論 (0)編輯 收藏

          hive大數(shù)據(jù)傾斜總結(jié)

          在做Shuffle階段的優(yōu)化過(guò)程中,遇到了數(shù)據(jù)傾斜的問(wèn)題,造成了對(duì)一些情況下優(yōu)化效果不明顯。主要是因?yàn)樵贘ob完成后的所得到的Counters是整個(gè)Job的總和,優(yōu)化是基于這些Counters得出的平均值,而由于數(shù)據(jù)傾斜的原因造成map處理數(shù)據(jù)量的差異過(guò)大,使得這些平均值能代表的價(jià)值降低。Hive的執(zhí)行是分階段的,map處理數(shù)據(jù)量的差異取決于上一個(gè)stage的reduce輸出,所以如何將數(shù)據(jù)均勻的分配到各個(gè)reduce中,就是解決數(shù)據(jù)傾斜的根本所在。規(guī)避錯(cuò)誤來(lái)更好的運(yùn)行比解決錯(cuò)誤更高效。在查看了一些資料后,總結(jié)如下。

          1數(shù)據(jù)傾斜的原因

          1.1操作:

          關(guān)鍵詞

          情形

          后果

          Join

          其中一個(gè)表較小,

          但是key集中

          分發(fā)到某一個(gè)或幾個(gè)Reduce上的數(shù)據(jù)遠(yuǎn)高于平均值

          大表與大表,但是分桶的判斷字段0值或空值過(guò)多

          這些空值都由一個(gè)reduce處理,灰常慢

          group by

          group by 維度過(guò)小,

          某值的數(shù)量過(guò)多

          處理某值的reduce灰常耗時(shí)

          Count Distinct

          某特殊值過(guò)多

          處理此特殊值的reduce耗時(shí)

          1.2原因:

          1)、key分布不均勻

          2)、業(yè)務(wù)數(shù)據(jù)本身的特性

          3)、建表時(shí)考慮不周

          4)、某些SQL語(yǔ)句本身就有數(shù)據(jù)傾斜

           

          1.3表現(xiàn):

          任務(wù)進(jìn)度長(zhǎng)時(shí)間維持在99%(或100%),查看任務(wù)監(jiān)控頁(yè)面,發(fā)現(xiàn)只有少量(1個(gè)或幾個(gè))reduce子任務(wù)未完成。因?yàn)槠涮幚淼臄?shù)據(jù)量和其他reduce差異過(guò)大。

          單一reduce的記錄數(shù)與平均記錄數(shù)差異過(guò)大,通常可能達(dá)到3倍甚至更多。 最長(zhǎng)時(shí)長(zhǎng)遠(yuǎn)大于平均時(shí)長(zhǎng)。

           

          2數(shù)據(jù)傾斜的解決方案

          2.1參數(shù)調(diào)節(jié):

          hive.map.aggr=true

          Map 端部分聚合,相當(dāng)于Combiner

          hive.groupby.skewindata=true

          有數(shù)據(jù)傾斜的時(shí)候進(jìn)行負(fù)載均衡,當(dāng)選項(xiàng)設(shè)定為 true,生成的查詢(xún)計(jì)劃會(huì)有兩個(gè) MR Job。第一個(gè) MR Job 中,Map 的輸出結(jié)果集合會(huì)隨機(jī)分布到 Reduce 中,每個(gè) Reduce 做部分聚合操作,并輸出結(jié)果,這樣處理的結(jié)果是相同的 Group By Key 有可能被分發(fā)到不同的 Reduce 中,從而達(dá)到負(fù)載均衡的目的;第二個(gè) MR Job 再根據(jù)預(yù)處理的數(shù)據(jù)結(jié)果按照 Group By Key 分布到 Reduce 中(這個(gè)過(guò)程可以保證相同的 Group By Key 被分布到同一個(gè) Reduce 中),最后完成最終的聚合操作。

           

          2.2 SQL語(yǔ)句調(diào)節(jié):

          如何Join

          關(guān)于驅(qū)動(dòng)表的選取,選用join key分布最均勻的表作為驅(qū)動(dòng)表

          做好列裁剪和filter操作,以達(dá)到兩表做join的時(shí)候,數(shù)據(jù)量相對(duì)變小的效果。

          大小表Join

          使用map join讓小的維度表(1000條以下的記錄條數(shù)) 先進(jìn)內(nèi)存。在map端完成reduce.

          大表Join大表:

          把空值的key變成一個(gè)字符串加上隨機(jī)數(shù),把傾斜的數(shù)據(jù)分到不同的reduce上,由于null值關(guān)聯(lián)不上,處理后并不影響最終結(jié)果。

          count distinct大量相同特殊值

          count distinct時(shí),將值為空的情況單獨(dú)處理,如果是計(jì)算count distinct,可以不用處理,直接過(guò)濾,在最后結(jié)果中加1。如果還有其他計(jì)算,需要進(jìn)行g(shù)roup by,可以先將值為空的記錄單獨(dú)處理,再和其他計(jì)算結(jié)果進(jìn)行union。

          group by維度過(guò)小:

          采用sum() group by的方式來(lái)替換count(distinct)完成計(jì)算。

          特殊情況特殊處理:

          在業(yè)務(wù)邏輯優(yōu)化效果的不大情況下,有些時(shí)候是可以將傾斜的數(shù)據(jù)單獨(dú)拿出來(lái)處理。最后union回去。

           

          3典型的業(yè)務(wù)場(chǎng)景

          3.1空值產(chǎn)生的數(shù)據(jù)傾斜

          場(chǎng)景:如日志中,常會(huì)有信息丟失的問(wèn)題,比如日志中的 user_id,如果取其中的 user_id 和 用戶(hù)表中的user_id 關(guān)聯(lián),會(huì)碰到數(shù)據(jù)傾斜的問(wèn)題。

          解決方法1 user_id為空的不參與關(guān)聯(lián)(紅色字體為修改后)

          復(fù)制代碼
          select * from log a   join users b   on a.user_id is not null   and a.user_id = b.user_id union all select * from log a   where a.user_id is null;
          復(fù)制代碼

           

          解決方法賦與空值分新的key值

          select *   from log a   left outer join users b   on case when a.user_id is null then concat(‘hive’,rand() ) else a.user_id end = b.user_id;

           

          結(jié)論:方法2比方法1效率更好,不但io少了,而且作業(yè)數(shù)也少了。解決方法1中 log讀取兩次,jobs是2。解決方法2 job數(shù)是1 。這個(gè)優(yōu)化適合無(wú)效 id (比如 -99 , ’’, null 等) 產(chǎn)生的傾斜問(wèn)題。把空值的 key 變成一個(gè)字符串加上隨機(jī)數(shù),就能把傾斜的數(shù)據(jù)分到不同的reduce上 ,解決數(shù)據(jù)傾斜問(wèn)題。

           

          3.2不同數(shù)據(jù)類(lèi)型關(guān)聯(lián)產(chǎn)生數(shù)據(jù)傾斜

          場(chǎng)景:用戶(hù)表中user_id字段為int,log表中user_id字段既有string類(lèi)型也有int類(lèi)型。當(dāng)按照user_id進(jìn)行兩個(gè)表的Join操作時(shí),默認(rèn)的Hash操作會(huì)按int型的id來(lái)進(jìn)行分配,這樣會(huì)導(dǎo)致所有string類(lèi)型id的記錄都分配到一個(gè)Reducer中。

          解決方法:把數(shù)字類(lèi)型轉(zhuǎn)換成字符串類(lèi)型

          select * from users a   left outer join logs b   on a.usr_id = cast(b.user_id as string)

           

          3.3小表不小不大,怎么用 map join 解決傾斜問(wèn)題

          使用 map join 解決小表(記錄數(shù)少)關(guān)聯(lián)大表的數(shù)據(jù)傾斜問(wèn)題,這個(gè)方法使用的頻率非常高,但如果小表很大,大到map join會(huì)出現(xiàn)bug或異常,這時(shí)就需要特別的處理。 以下例子:

          select * from log a   left outer join users b   on a.user_id = b.user_id;

           

          users 表有 600w+ 的記錄,把 users 分發(fā)到所有的 map 上也是個(gè)不小的開(kāi)銷(xiāo),而且 map join 不支持這么大的小表。如果用普通的 join,又會(huì)碰到數(shù)據(jù)傾斜的問(wèn)題。

          解決方法:

          select /*+mapjoin(x)*/* from log a   
          left outer join (
          select /*+mapjoin(c)*/d.* from (
          select distinct user_id from log ) c join users d
          on c.user_id = d.user_id ) x
          on a.user_id = b.user_id;

          假如,log里user_id有上百萬(wàn)個(gè),這就又回到原來(lái)map join問(wèn)題。所幸,每日的會(huì)員uv不會(huì)太多,有交易的會(huì)員不會(huì)太多,有點(diǎn)擊的會(huì)員不會(huì)太多,有傭金的會(huì)員不會(huì)太多等等。所以這個(gè)方法能解決很多場(chǎng)景下的數(shù)據(jù)傾斜問(wèn)題。

          4總結(jié)

          使map的輸出數(shù)據(jù)更均勻的分布到reduce中去,是我們的最終目標(biāo)。由于Hash算法的局限性,按key Hash會(huì)或多或少的造成數(shù)據(jù)傾斜。大量經(jīng)驗(yàn)表明數(shù)據(jù)傾斜的原因是人為的建表疏忽或業(yè)務(wù)邏輯可以規(guī)避的。在此給出較為通用的步驟:

          1、采樣log表,哪些user_id比較傾斜,得到一個(gè)結(jié)果表tmp1。由于對(duì)計(jì)算框架來(lái)說(shuō),所有的數(shù)據(jù)過(guò)來(lái),他都是不知道數(shù)據(jù)分布情況的,所以采樣是并不可少的。

          2、數(shù)據(jù)的分布符合社會(huì)學(xué)統(tǒng)計(jì)規(guī)則,貧富不均。傾斜的key不會(huì)太多,就像一個(gè)社會(huì)的富人不多,奇特的人不多一樣。所以tmp1記錄數(shù)會(huì)很少。把tmp1和users做map join生成tmp2,把tmp2讀到distribute file cache。這是一個(gè)map過(guò)程。

          3、map讀入users和log,假如記錄來(lái)自log,則檢查user_id是否在tmp2里,如果是,輸出到本地文件a,否則生成<user_id,value>的key,value對(duì),假如記錄來(lái)自member,生成<user_id,value>的key,value對(duì),進(jìn)入reduce階段。

          4、最終把a(bǔ)文件,把Stage3 reduce階段輸出的文件合并起寫(xiě)到hdfs。

           

          如果確認(rèn)業(yè)務(wù)需要這樣傾斜的邏輯,考慮以下的優(yōu)化方案:

          1、對(duì)于join,在判斷小表不大于1G的情況下,使用map join

          2、對(duì)于group by或distinct,設(shè)定 hive.groupby.skewindata=true

          3、盡量使用上述的SQL語(yǔ)句調(diào)節(jié)進(jìn)行優(yōu)化

          posted @ 2017-07-31 19:57 鴻雁 閱讀(191) | 評(píng)論 (0)編輯 收藏

          Hive性能調(diào)優(yōu)

          Hive的一般學(xué)習(xí)者和培訓(xùn)者在談性能優(yōu)化的時(shí)候一般都會(huì)從語(yǔ)法和參數(shù)這些雕蟲(chóng)小技的角度談優(yōu)化,而不會(huì)革命性的優(yōu)化Hive的性能,產(chǎn)生這種現(xiàn)象的原因有:
          1,歷史原因和思維定勢(shì):大家學(xué)習(xí)SQL的時(shí)候一般都是就單機(jī)DB,這個(gè)時(shí)候你的性能優(yōu)化技巧確實(shí)主要是SQL語(yǔ)法和參數(shù)調(diào)優(yōu);
          2,Hive的核心的性能問(wèn)題往往是產(chǎn)生在超過(guò)規(guī)模數(shù)據(jù)集,例如說(shuō)100億條級(jí)別的數(shù)據(jù)集,以及每天處理上千上萬(wàn)個(gè)Hive作業(yè)的情況下產(chǎn)生的;

          上面的第二點(diǎn)是我們現(xiàn)在Hive性能調(diào)優(yōu)部分要徹底解決的內(nèi)容;

          要從根本上解決和顯著的解決實(shí)際企業(yè)中Hive真正的性能優(yōu)化問(wèn)題,必須考慮到底什么是Hive性能的限制,我們按照優(yōu)先級(jí)來(lái)說(shuō):
          第一重要的是:戰(zhàn)略性架構(gòu)
           解決海量數(shù)據(jù)下大量Job過(guò)于頻繁的IO問(wèn)題,而這個(gè)問(wèn)題實(shí)質(zhì)上涉及了架構(gòu)方面的分表 數(shù)據(jù)復(fù)用 以及分區(qū)表等調(diào)優(yōu)的方式;
              補(bǔ)充:1,海量的數(shù)據(jù)中有些數(shù)據(jù)是高頻使用的數(shù)據(jù),而有些是很少使用的,如果能夠分離成為不同的表,會(huì)極大的提升效率;很多的作業(yè)可能會(huì)有共同點(diǎn),抽離出來(lái)先進(jìn)行計(jì)算并保留計(jì)算結(jié)果,后面的作業(yè)都可以復(fù)用;同時(shí),底層的基礎(chǔ)功能
          也可以先計(jì)算,在上層應(yīng)用的時(shí)候直接拿數(shù)據(jù)結(jié)果,而不是每次都重復(fù)計(jì)算;
              2,合理從用靜態(tài)分區(qū)表和動(dòng)態(tài)分區(qū)表,可以避免數(shù)據(jù)全局掃描及計(jì)算資源更合理的利用;

              3,數(shù)據(jù)傾斜的一站式解決方案;
          第二重要的是:引擎和物理層面,很多內(nèi)容都是普通Hive使用這不知道的!
              從Hive語(yǔ)法和Job內(nèi)部的角度去進(jìn)行優(yōu)化,這要求MapReduce以及Hive如何被翻譯成為MapReduce要非常精通;

          第三重要的是:一些關(guān)鍵的參數(shù);



          歸根到底,Hive的性能優(yōu)化主要考慮的是如何最大化和最有效的使用CPU Memory IO;



          Hive背后的Mapper調(diào)優(yōu):
          1,Mapper數(shù)過(guò)大,會(huì)產(chǎn)生大量小文件,由于Mapper是基于虛擬機(jī)的,過(guò)多的Mapper創(chuàng)建和初始化及關(guān)閉虛擬機(jī)都會(huì)消耗大量的硬件資源;
              Mapper數(shù)太小,并發(fā)度過(guò)小,Job執(zhí)行時(shí)間過(guò)長(zhǎng),無(wú)法充分利用分布式硬件資源;
          2,Mapper數(shù)據(jù)由什么決定呢?
              輸入文件數(shù)目;
              輸入文件的大小;
              配置參數(shù);
           默認(rèn)情況下:例如一個(gè)文件800M,BLock大小是128M,那么Mapper數(shù)目就是7個(gè),6個(gè)Mapper處理的數(shù)據(jù)是 128M, 1個(gè)Mapper處理的數(shù)據(jù)是32M;再例如,一個(gè)目錄下有三個(gè)文件分別大小問(wèn)5M 10M 150M
           此時(shí)會(huì)產(chǎn)生4個(gè)Mapper,處理的數(shù)據(jù)分別是5M 10M 128M 22M;
            
           減少M(fèi)apper的個(gè)數(shù),就要合并小文件,這種小文件有可能是直接來(lái)自于數(shù)據(jù)源的小文件,也可能是Reducer產(chǎn)生的小文件;
              set hive.input.format=org.apache.Hadoop.hive.ql.io.CombineHiveInputFormat;
              set hive.merge.mapFiles=true;
              set hive.merge.mapredFiles=true;
              set hive.merge.size.per.task=256000000
              set mapred.max.split.size=256000000
              set mapred.min.split.size.per.node=128000000
              
              
           增加Mapper的個(gè)數(shù),一般是通過(guò)控制Hive SQL中上一個(gè)Job的Reducer個(gè)數(shù)來(lái)控制的,例如在Join操作的時(shí)候會(huì)把多個(gè)表分解為多個(gè)Job;


           set mapred.map.tasks=2;
           set hive.merge.mapFiles=true;
           set hive.merge.mapredFiles=true;
           set hive.merge.size.per.task=256000000

           例如我們有5個(gè)300M的文件;按照上面的配置會(huì)產(chǎn)生10個(gè)Mapper,5個(gè)Mapper處理的都是256M的數(shù)據(jù),另外5個(gè)Mapper處理的都是44M的數(shù)據(jù),問(wèn)題是:大的Mapper會(huì)數(shù)據(jù)傾斜
          如何解決,設(shè)置set mapred.map.tasks=6,此時(shí)根據(jù)MapRed的運(yùn)行機(jī)制,會(huì)劃分6個(gè)Mapper,每個(gè)Mapper的處理數(shù)據(jù)的大小是250M, min(1500M/6, 256M) =250M

          Hive背后的Reducer調(diào)優(yōu):
          1,Reducer數(shù)目過(guò)大的話(huà),會(huì)產(chǎn)生很多小文件,每個(gè)Reducer都會(huì)產(chǎn)生一個(gè)文件,如果這些小文件是下一個(gè)JOB的輸入,則會(huì)需要對(duì)小文件進(jìn)行合并;同樣啟動(dòng) 初始化和銷(xiāo)毀Reducer的虛擬機(jī)也需要消耗大量的硬件;
            Reducer數(shù)據(jù)過(guò)小的話(huà),Reduce的時(shí)間會(huì)比較長(zhǎng),也可能會(huì)出現(xiàn)數(shù)據(jù)傾斜;
          2,如何控制Reducer的個(gè)數(shù)呢?
            set hive.exec.reducers.byte.per.reducer=1G
            set hive.exec.reducers.max=999
            Reducer個(gè)數(shù)=min(999, Reducer的數(shù)據(jù)輸入總量/1G);

            set mapred.reduce.tasks = 10, 默認(rèn)是1; 如果說(shuō)當(dāng)前的Reducer的結(jié)果很大,且被接下來(lái)多個(gè)Job使用其結(jié)果,我們?cè)撊绾卧O(shè)置參數(shù)呢?一般都需要調(diào)大該參數(shù);

            什么情況下只有一個(gè)Reducer?如果不進(jìn)行Group by但卻需要匯總,或者說(shuō)Order by,當(dāng)然如果最后Reducer的數(shù)據(jù)小于默認(rèn)的1G的話(huà),也會(huì)只有一個(gè)Reducer;


          1,Hive在分布式運(yùn)行的時(shí)候最害怕的是數(shù)據(jù)傾斜,這是由于分布式系統(tǒng)的特性決定的,因?yàn)榉植际较到y(tǒng)之所以很快是由于作業(yè)平均分配給了不同的節(jié)點(diǎn),不同節(jié)點(diǎn)同心協(xié)力,從而達(dá)到更快處理完作業(yè)的目的;
          順便說(shuō)明一下,處理數(shù)據(jù)傾斜的能力是hadoopSpark工程師最核心的競(jìng)爭(zhēng)力之一;

          2,Hive中數(shù)據(jù)傾斜的原因:
              數(shù)據(jù)在分布式節(jié)點(diǎn)上分布不平衡;
              join時(shí)某些key可能特別大;
              groupBy的時(shí)候某個(gè)Key可能特別多;
              count(distinct)有可能出現(xiàn)數(shù)據(jù)傾斜,因?yàn)槠鋬?nèi)部首先會(huì)進(jìn)行g(shù)roupBy操作;


          3,join,我們希望join時(shí)候key是分散,如果一個(gè)key的數(shù)據(jù)量特別大,有可能會(huì)出現(xiàn)數(shù)據(jù)傾斜和OOM,一個(gè)核心點(diǎn)是:小表join大表,在reduce階段左側(cè)的小表會(huì)加載進(jìn)內(nèi)存,減少OOM的風(fēng)險(xiǎn);
          4,大表join大表的情況:數(shù)據(jù)傾斜,例如null值,解決辦法一般是要打散null值,例如說(shuō)使用隨機(jī)數(shù)等,如果數(shù)據(jù)傾斜比較嚴(yán)重,采用這種方式可以提升至少一倍的速度;
          5,mapJoin:小表join(超)大表的時(shí)候,可以采用mapJoin的方式把小表全部加載到Mapper端的內(nèi)存中/*+MAPJOIN(table_name)*/;
          6,小表join(超)大表的時(shí)候,是否會(huì)自動(dòng)進(jìn)行mapJoin,想進(jìn)行mapJoin,需要設(shè)置:set hive.auto.convert.join=true,Hive在進(jìn)行join的時(shí)候會(huì)判斷左表的大小來(lái)決定是否進(jìn)行mapJoin:
              set hive.mapjoin.smalltable.filesize=128000000;
              set hive.mapjoin.cache.numrows=100000;
              上述參數(shù)可以根據(jù)實(shí)際的硬件機(jī)器的內(nèi)存進(jìn)行調(diào)整,對(duì)性能有至關(guān)重要的影響,因?yàn)闆](méi)有了Shuffle;
            對(duì)于mapJoin我們能夠使用Mapper端JVM中多大的內(nèi)存呢?
              set hive.mapjoin.followby.gby.localtask.max.momery.usage = 0.8
              set hive.mapjoin.localtask.max.memory.uage=0.9
          7,groupBy,我們可以設(shè)置在Mapper端進(jìn)行部分聚合,最后在Reducer端進(jìn)行全局聚合
              set hive.map.aggr=true;
              set hive.groupby.mapaggr.checkinterval=100000

              set hive.groupby.skewindata = true 內(nèi)部會(huì)產(chǎn)生兩個(gè)Job,第一個(gè)Job會(huì)通過(guò)自己的算法打散傾斜的Key并進(jìn)行聚合操作且保留結(jié)果,第二個(gè)Job會(huì)完成全部的groupBy操作,會(huì)產(chǎn)生Mapper-Reducer-Reducer的結(jié)構(gòu)

          8, count(distinct),如果某個(gè)字段特別多,容易產(chǎn)生數(shù)據(jù)傾斜,解決思路:
              在查詢(xún)語(yǔ)句中例如對(duì)null進(jìn)行過(guò)濾,在結(jié)果中加1


          9, 笛卡爾積:join時(shí)候沒(méi)有on條件,或者on條件無(wú)效,這個(gè)時(shí)候會(huì)使用Reducer進(jìn)行笛卡爾積的操作;

          posted @ 2017-07-30 13:52 鴻雁 閱讀(202) | 評(píng)論 (0)編輯 收藏

          HIVE和HBASE區(qū)別

          1. 兩者分別是什么?  

           Apache Hive是一個(gè)構(gòu)建在Hadoop基礎(chǔ)設(shè)施之上的數(shù)據(jù)倉(cāng)庫(kù)。通過(guò)Hive可以使用HQL語(yǔ)言查詢(xún)存放在HDFS上的數(shù)據(jù)。HQL是一種類(lèi)SQL語(yǔ)言,這種語(yǔ)言最終被轉(zhuǎn)化為Map/Reduce. 雖然Hive提供了SQL查詢(xún)功能,但是Hive不能夠進(jìn)行交互查詢(xún)--因?yàn)樗荒軌蛟贖aoop上批量的執(zhí)行Hadoop。

              Apache HBase是一種Key/Value系統(tǒng),它運(yùn)行在HDFS之上。和Hive不一樣,Hbase的能夠在它的數(shù)據(jù)庫(kù)上實(shí)時(shí)運(yùn)行,而不是運(yùn)行MapReduce任務(wù)。Hive被分區(qū)為表格,表格又被進(jìn)一步分割為列簇。列簇必須使用schema定義,列簇將某一類(lèi)型列集合起來(lái)(列不要求schema定義)。例如,“message”列簇可能包含:“to”, ”from” “date”, “subject”, 和”body”. 每一個(gè) key/value對(duì)在Hbase中被定義為一個(gè)cell,每一個(gè)key由row-key,列簇、列和時(shí)間戳。在Hbase中,行是key/value映射的集合,這個(gè)映射通過(guò)row-key來(lái)唯一標(biāo)識(shí)。Hbase利用Hadoop的基礎(chǔ)設(shè)施,可以利用通用的設(shè)備進(jìn)行水平的擴(kuò)展。

          2. 兩者的特點(diǎn)

            Hive幫助熟悉SQL的人運(yùn)行MapReduce任務(wù)。因?yàn)樗荍DBC兼容的,同時(shí),它也能夠和現(xiàn)存的SQL工具整合在一起。運(yùn)行Hive查詢(xún)會(huì)花費(fèi)很長(zhǎng)時(shí)間,因?yàn)樗鼤?huì)默認(rèn)遍歷表中所有的數(shù)據(jù)。雖然有這樣的缺點(diǎn),一次遍歷的數(shù)據(jù)量可以通過(guò)Hive的分區(qū)機(jī)制來(lái)控制。分區(qū)允許在數(shù)據(jù)集上運(yùn)行過(guò)濾查詢(xún),這些數(shù)據(jù)集存儲(chǔ)在不同的文件夾內(nèi),查詢(xún)的時(shí)候只遍歷指定文件夾(分區(qū))中的數(shù)據(jù)。這種機(jī)制可以用來(lái),例如,只處理在某一個(gè)時(shí)間范圍內(nèi)的文件,只要這些文件名中包括了時(shí)間格式。

              HBase通過(guò)存儲(chǔ)key/value來(lái)工作。它支持四種主要的操作:增加或者更新行,查看一個(gè)范圍內(nèi)的cell,獲取指定的行,刪除指定的行、列或者是列的版本。版本信息用來(lái)獲取歷史數(shù)據(jù)(每一行的歷史數(shù)據(jù)可以被刪除,然后通過(guò)Hbase compactions就可以釋放出空間)。雖然HBase包括表格,但是schema僅僅被表格和列簇所要求,列不需要schema。Hbase的表格包括增加/計(jì)數(shù)功能。

          3. 限制

            Hive目前不支持更新操作。另外,由于hive在hadoop上運(yùn)行批量操作,它需要花費(fèi)很長(zhǎng)的時(shí)間,通常是幾分鐘到幾個(gè)小時(shí)才可以獲取到查詢(xún)的結(jié)果。Hive必須提供預(yù)先定義好的schema將文件和目錄映射到列,并且Hive與ACID不兼容。

              HBase查詢(xún)是通過(guò)特定的語(yǔ)言來(lái)編寫(xiě)的,這種語(yǔ)言需要重新學(xué)習(xí)。類(lèi)SQL的功能可以通過(guò)Apache Phonenix實(shí)現(xiàn),但這是以必須提供schema為代價(jià)的。另外,Hbase也并不是兼容所有的ACID特性,雖然它支持某些特性。最后但不是最重要的--為了運(yùn)行Hbase,Zookeeper是必須的,zookeeper是一個(gè)用來(lái)進(jìn)行分布式協(xié)調(diào)的服務(wù),這些服務(wù)包括配置服務(wù),維護(hù)元信息和命名空間服務(wù)。

          4. 應(yīng)用場(chǎng)景

              Hive適合用來(lái)對(duì)一段時(shí)間內(nèi)的數(shù)據(jù)進(jìn)行分析查詢(xún),例如,用來(lái)計(jì)算趨勢(shì)或者網(wǎng)站的日志。Hive不應(yīng)該用來(lái)進(jìn)行實(shí)時(shí)的查詢(xún)。因?yàn)樗枰荛L(zhǎng)時(shí)間才可以返回結(jié)果。

              Hbase非常適合用來(lái)進(jìn)行大數(shù)據(jù)的實(shí)時(shí)查詢(xún)。Facebook用Hbase進(jìn)行消息和實(shí)時(shí)的分析。它也可以用來(lái)統(tǒng)計(jì)Facebook的連接數(shù)。

          5. 總結(jié)

              Hive和Hbase是兩種基于Hadoop的不同技術(shù)--Hive是一種類(lèi)SQL的引擎,并且運(yùn)行MapReduce任務(wù),Hbase是一種在Hadoop之上的NoSQL 的Key/vale數(shù)據(jù)庫(kù)。當(dāng)然,這兩種工具是可以同時(shí)使用的。就像用Google來(lái)搜索,用FaceBook進(jìn)行社交一樣,Hive可以用來(lái)進(jìn)行統(tǒng)計(jì)查詢(xún),HBase可以用來(lái)進(jìn)行實(shí)時(shí)查詢(xún),數(shù)據(jù)也可以從Hive寫(xiě)到Hbase,設(shè)置再?gòu)腍base寫(xiě)回Hive。

          posted @ 2017-07-21 11:44 鴻雁 閱讀(171) | 評(píng)論 (0)編輯 收藏

          Hive分布式安裝配置Hive+Mysql

               摘要: 目錄 1,環(huán)境準(zhǔn)備 2,安裝Hive和配置環(huán)境變量 3,安裝MySQL 4,在mysql上創(chuàng)建hive元數(shù)據(jù)庫(kù),并對(duì)hive進(jìn)行授權(quán) 5,安裝jar包到hive 6,配置hive-site.xml 7,元數(shù)據(jù)存儲(chǔ)初始化 8,啟動(dòng)驗(yàn)證hive 9,報(bào)錯(cuò)及解決方法 1,環(huán)境準(zhǔn)備: 準(zhǔn)備好Hadoop集群,參照...  閱讀全文

          posted @ 2017-07-20 15:20 鴻雁 閱讀(469) | 評(píng)論 (0)編輯 收藏

          TCP/UDP區(qū)別以及UDP如何實(shí)現(xiàn)可靠傳輸

          TCP和UDP是OSI模型中的運(yùn)輸層中的協(xié)議。TCP提供可靠的通信傳輸,而UDP則常被用于讓廣播和細(xì)節(jié)控制交給應(yīng)用的通信傳輸。


          UDP(User Datagram Protocol)

                  UDP不提供復(fù)雜的控制機(jī)制,利用IP提供面向無(wú)連接的通信服務(wù)。并且它是將應(yīng)用程序發(fā)來(lái)的數(shù)據(jù)在收到的那一刻,立刻按照原樣發(fā)送到網(wǎng)絡(luò)上的一種機(jī)制。

                  即使是出現(xiàn)網(wǎng)絡(luò)擁堵的情況下,UDP也無(wú)法進(jìn)行流量控制等避免網(wǎng)絡(luò)擁塞的行為。此外,傳輸途中如果出現(xiàn)了丟包,UDO也不負(fù)責(zé)重發(fā)。甚至當(dāng)出現(xiàn)包的到達(dá)順序亂掉時(shí)也沒(méi)有糾正的功能。如果需要這些細(xì)節(jié)控制,那么不得不交給由采用UDO的應(yīng)用程序去處理。換句話(huà)說(shuō),UDP將部分控制轉(zhuǎn)移到應(yīng)用程序去處理,自己卻只提供作為傳輸層協(xié)議的最基本功能。UDP有點(diǎn)類(lèi)似于用戶(hù)說(shuō)什么聽(tīng)什么的機(jī)制,但是需要用戶(hù)充分考慮好上層協(xié)議類(lèi)型并制作相應(yīng)的應(yīng)用程序。


          TCP(Transmission Control Protocol)

                  TCP充分實(shí)現(xiàn)愛(ài)呢了數(shù)據(jù)傳輸時(shí)各種控制功能,可以進(jìn)行丟包的重發(fā)控制,還可以對(duì)次序亂掉的分包進(jìn)行順序控制。而這些在UDP中都沒(méi)有。此外,TCP作為一種面向有連接的協(xié)議,只有在確認(rèn)通信對(duì)端存在時(shí)才會(huì)發(fā)送數(shù)據(jù),從而可以控制通信流量的浪費(fèi)。

                  TCP通過(guò)檢驗(yàn)和、序列號(hào)、確認(rèn)應(yīng)答、重發(fā)控制、連接管理以及窗口控制等機(jī)制實(shí)現(xiàn)可靠性傳輸。此處不一一敘述。


          TCP與UDP如何加以區(qū)分使用?

                  TCP用于在傳輸層有必要實(shí)現(xiàn)可靠性傳輸?shù)那闆r。由于它是面向有連接并具備順序控制、重發(fā)控制等機(jī)制的。所以它可以為應(yīng)用提供可靠傳輸。

                  另一方面,UDP主要用于那些對(duì)高速傳輸和實(shí)時(shí)性有較高要求的通信或廣播通信。舉一個(gè)IP電話(huà)進(jìn)行通話(huà)的例子。如果使用TCP,數(shù)據(jù)在傳送途中如果丟失會(huì)被重發(fā),但是這樣無(wú)法流暢地傳輸通話(huà)人的聲音,會(huì)導(dǎo)致無(wú)法進(jìn)行正常交流。而采用UDP,它不會(huì)進(jìn)行重發(fā)處理。從而也就不會(huì)有聲音大幅度延遲到達(dá)的問(wèn)題。即使有部分?jǐn)?shù)據(jù)丟失,也只是影響某一小部分的通話(huà)。此外,在多播與廣播通信中也使用UDP而不是UDP。RIP、DHCP等基于廣播的協(xié)議也要依賴(lài)于UDP。


          TCP與UDP區(qū)別總結(jié):

          1、TCP面向連接(如打電話(huà)要先撥號(hào)建立連接);UDP是無(wú)連接的,即發(fā)送數(shù)據(jù)之前不需要建立連接

          2、TCP提供可靠的服務(wù)。也就是說(shuō),通過(guò)TCP連接傳送的數(shù)據(jù),無(wú)差錯(cuò),不丟失,不重復(fù),且按序到達(dá);UDP盡最大努力交付,即不保證可靠交付
          3、TCP面向字節(jié)流,實(shí)際上是TCP把數(shù)據(jù)看成一連串無(wú)結(jié)構(gòu)的字節(jié)流;UDP是面向報(bào)文的
          UDP沒(méi)有擁塞控制,因此網(wǎng)絡(luò)出現(xiàn)擁塞不會(huì)使源主機(jī)的發(fā)送速率降低(對(duì)實(shí)時(shí)應(yīng)用很有用,如IP電話(huà),實(shí)時(shí)視頻會(huì)議等)
          4、每一條TCP連接只能是點(diǎn)到點(diǎn)的;UDP支持一對(duì)一,一對(duì)多,多對(duì)一和多對(duì)多的交互通信
          5、TCP首部開(kāi)銷(xiāo)20字節(jié);UDP的首部開(kāi)銷(xiāo)小,只有8個(gè)字節(jié)

          6、TCP的邏輯通信信道是全雙工的可靠信道,UDP則是不可靠信道


          UDP如何實(shí)現(xiàn)可靠傳輸

          由于在傳輸層UDP已經(jīng)是不可靠的連接,那就要在應(yīng)用層自己實(shí)現(xiàn)一些保障可靠傳輸?shù)臋C(jī)制

          簡(jiǎn)單來(lái)講,要使用UDP來(lái)構(gòu)建可靠的面向連接的數(shù)據(jù)傳輸,就要實(shí)現(xiàn)類(lèi)似于TCP協(xié)議的

          超時(shí)重傳(定時(shí)器)

          有序接受 (添加包序號(hào))

          應(yīng)答確認(rèn) (Seq/Ack應(yīng)答機(jī)制)

          滑動(dòng)窗口流量控制等機(jī)制 (滑動(dòng)窗口協(xié)議)

          等于說(shuō)要在傳輸層的上一層(或者直接在應(yīng)用層)實(shí)現(xiàn)TCP協(xié)議的可靠數(shù)據(jù)傳輸機(jī)制,比如使用UDP數(shù)據(jù)包+序列號(hào),UDP數(shù)據(jù)包+時(shí)間戳等方法。

          目前已經(jīng)有一些實(shí)現(xiàn)UDP可靠傳輸?shù)臋C(jī)制,比如

          UDT(UDP-based Data Transfer Protocol

          基于UDP的數(shù)據(jù)傳輸協(xié)議(UDP-based Data Transfer Protocol,簡(jiǎn)稱(chēng)UDT)是一種互聯(lián)網(wǎng)數(shù)據(jù)傳輸協(xié)議。UDT的主要目的是支持高速?gòu)V域網(wǎng)上的海量數(shù)據(jù)傳輸,而互聯(lián)網(wǎng)上的標(biāo)準(zhǔn)數(shù)據(jù)傳輸協(xié)議TCP在高帶寬長(zhǎng)距離網(wǎng)絡(luò)上性能很差。 顧名思義,UDT建于UDP之上,并引入新的擁塞控制和數(shù)據(jù)可靠性控制機(jī)制。UDT是面向連接的雙向的應(yīng)用層協(xié)議。它同時(shí)支持可靠的數(shù)據(jù)流傳輸和部分可靠的數(shù)據(jù)報(bào)傳輸。 由于UDT完全在UDP上實(shí)現(xiàn),它也可以應(yīng)用在除了高速數(shù)據(jù)傳輸之外的其它應(yīng)用領(lǐng)域,例如點(diǎn)到點(diǎn)技術(shù)(P2P),防火墻穿透,多媒體數(shù)據(jù)傳輸?shù)鹊取?/span>

          posted @ 2017-07-19 22:25 鴻雁 閱讀(470) | 評(píng)論 (0)編輯 收藏

          一文讀懂分布式數(shù)據(jù)庫(kù)Hbase

          一、

          1、什么是Hbase

          一個(gè)高可靠性、高性能、列存儲(chǔ)、可伸縮、實(shí)時(shí)讀寫(xiě)的分布式數(shù)據(jù)庫(kù)系統(tǒng)。

          適合于存儲(chǔ)非結(jié)構(gòu)化數(shù)據(jù),基于列的而不是基于行的模式

          如圖:Hadoop生態(tài)中hbase與其他部分的關(guān)系。


          2、關(guān)系數(shù)據(jù)庫(kù)已經(jīng)流行很多年,并且hadoop已經(jīng)有了HDFS和MapReduce,為什么需要HBase?

          Hadoop可以很好地解決大規(guī)模數(shù)據(jù)的離線(xiàn)批量處理問(wèn)題,但是,受限于HadoopMapReduce編程框架的高延遲數(shù)據(jù)處理機(jī)制,使得Hadoop無(wú)法滿(mǎn)足大規(guī)模數(shù)據(jù)實(shí)時(shí)處理應(yīng)用的需求
          HDFS面向批量訪(fǎng)問(wèn)模式,不是隨機(jī)訪(fǎng)問(wèn)模式
          傳統(tǒng)的通用關(guān)系型數(shù)據(jù)庫(kù)無(wú)法應(yīng)對(duì)在數(shù)據(jù)規(guī)模劇增時(shí)導(dǎo)致的系統(tǒng)擴(kuò)展性和性能問(wèn)題(分庫(kù)分表也不能很好解決)
          傳統(tǒng)關(guān)系數(shù)據(jù)庫(kù)在數(shù)據(jù)結(jié)構(gòu)變化時(shí)一般需要停機(jī)維護(hù);空列浪費(fèi)存儲(chǔ)空間
          因此,業(yè)界出現(xiàn)了一類(lèi)面向半結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)和處理的高可擴(kuò)展、低寫(xiě)入/查詢(xún)延遲的系統(tǒng),例如,鍵值數(shù)據(jù)庫(kù)、文檔數(shù)據(jù)庫(kù)和列族數(shù)據(jù)庫(kù)(如BigTableHBase等)
          HBase已經(jīng)成功應(yīng)用于互聯(lián)網(wǎng)服務(wù)領(lǐng)域和傳統(tǒng)行業(yè)的眾多在線(xiàn)式數(shù)據(jù)分析處理系統(tǒng)中
          3、HBase與傳統(tǒng)的關(guān)系數(shù)據(jù)庫(kù)的區(qū)別

          1)數(shù)據(jù)類(lèi)型:關(guān)系數(shù)據(jù)庫(kù)采用關(guān)系模型,具有豐富的數(shù)據(jù)類(lèi)型和存儲(chǔ)方式,HBase則采用了更加簡(jiǎn)單的數(shù)據(jù)模型,它把數(shù)據(jù)存儲(chǔ)為未經(jīng)解釋的字符串
          2)數(shù)據(jù)操作:關(guān)系數(shù)據(jù)庫(kù)中包含了豐富的操作,其中會(huì)涉及復(fù)雜的多表連接。HBase操作則不存在復(fù)雜的表與表之間的關(guān)系,只有簡(jiǎn)單的插入、查詢(xún)、刪除、清空等,因?yàn)?/span>HBase在設(shè)計(jì)上就避免了復(fù)雜的表和表之間的關(guān)系
          3)存儲(chǔ)模式:關(guān)系數(shù)據(jù)庫(kù)是基于行模式存儲(chǔ)的。HBase是基于列存儲(chǔ)的,每個(gè)列族都由幾個(gè)文件保存,不同列族的文件是分離的
          4)數(shù)據(jù)索引:關(guān)系數(shù)據(jù)庫(kù)通常可以針對(duì)不同列構(gòu)建復(fù)雜的多個(gè)索引,以提高數(shù)據(jù)訪(fǎng)問(wèn)性能。HBase只有一個(gè)索引——行鍵,通過(guò)巧妙的設(shè)計(jì),HBase中的所有訪(fǎng)問(wèn)方法,或者通過(guò)行鍵訪(fǎng)問(wèn),或者通過(guò)行鍵掃描,從而使得整個(gè)系統(tǒng)不會(huì)慢下來(lái)
          5)數(shù)據(jù)維護(hù):在關(guān)系數(shù)據(jù)庫(kù)中,更新操作會(huì)用最新的當(dāng)前值去替換記錄中原來(lái)的舊值,舊值被覆蓋后就不會(huì)存在。而HBase中執(zhí)行更新操作時(shí),并不會(huì)刪除數(shù)據(jù)舊的版本,而是生成一個(gè)新的版本,舊有的版本仍然保留
          6)可伸縮性:關(guān)系數(shù)據(jù)庫(kù)很難實(shí)現(xiàn)橫向擴(kuò)展,縱向擴(kuò)展的空間也比較有限。相反,HBase和BigTable這些分布式數(shù)據(jù)庫(kù)就是為了實(shí)現(xiàn)靈活的水平擴(kuò)展而開(kāi)發(fā)的,能夠輕易地通過(guò)在集群中增加或者減少硬件數(shù)量來(lái)實(shí)現(xiàn)性能的伸縮
          二、Hbase數(shù)據(jù)模型

          1、模型概述

          HBase是一個(gè)稀疏、多維度、排序的映射表,這張表的索引是行鍵、列族、列限定符和時(shí)間戳
          每個(gè)值是一個(gè)未經(jīng)解釋的字符串,沒(méi)有數(shù)據(jù)類(lèi)型
          用戶(hù)在表中存儲(chǔ)數(shù)據(jù),每一行都有一個(gè)可排序的行鍵和任意多的列
          表在水平方向由一個(gè)或者多個(gè)列族組成,一個(gè)列族中可以包含任意多個(gè)列,同一個(gè)列族里面的數(shù)據(jù)存儲(chǔ)在一起
          列族支持動(dòng)態(tài)擴(kuò)展,可以很輕松地添加一個(gè)列族或列,無(wú)需預(yù)先定義列的數(shù)量以及類(lèi)型,所有列均以字符串形式存儲(chǔ),用戶(hù)需要自行進(jìn)行數(shù)據(jù)類(lèi)型轉(zhuǎn)換
          HBase中執(zhí)行更新操作時(shí),并不會(huì)刪除數(shù)據(jù)舊的版本,而是生成一個(gè)新的版本,舊有的版本仍然保留(這是和HDFS只允許追加不允許修改的特性相關(guān)的)

          2、數(shù)據(jù)坐標(biāo)
          HBase
          中需要根據(jù)行鍵、列族、列限定符和時(shí)間戳來(lái)確定一個(gè)單元格,因此,可以視為一個(gè)“四維坐標(biāo)”,即[行鍵,列族, 列限定符,時(shí)間戳]

          [201505003,Info,email, 1174184619081]

          xie@qq.com

          [201505003,Info,email, 1174184620720]

          you@163.com


          3、概念視圖

          4、物理視圖


          三、HBase實(shí)現(xiàn)原理

          1、HBase的實(shí)現(xiàn)包括三個(gè)主要的功能組件:

          1)庫(kù)函數(shù):鏈接到每個(gè)客戶(hù)端
          2)一個(gè)Master主服務(wù)器
          3)許多個(gè)Region服務(wù)器
          主服務(wù)器Master負(fù)責(zé)管理和維護(hù)HBase表的分區(qū)信息,維護(hù)Region服務(wù)器列表,分配Region,負(fù)載均衡
          Region服務(wù)器負(fù)責(zé)存儲(chǔ)和維護(hù)分配給自己的Region,處理來(lái)自客戶(hù)端的讀寫(xiě)請(qǐng)求
          客戶(hù)端并不是直接從Master主服務(wù)器上讀取數(shù)據(jù),而是在獲得Region的存儲(chǔ)位置信息后,直接從Region服務(wù)器上讀取數(shù)據(jù)
          客戶(hù)端并不依賴(lài)Master,而是通過(guò)Zookeeper來(lái)獲得Region位置信息,大多數(shù)客戶(hù)端甚至從來(lái)不和Master通信,這種設(shè)計(jì)方式使得Master負(fù)載很小
          2、Region
          開(kāi)始只有一個(gè)
          Region,后來(lái)不斷分裂
          Region拆分操作非常快,接近瞬間,因?yàn)椴鸱种蟮?/span>Region讀取的仍然是原存儲(chǔ)文件,直到“合并”過(guò)程把存儲(chǔ)文件異步地寫(xiě)到獨(dú)立的文件之后,才會(huì)讀取新文件
          同一個(gè)Region不會(huì)被分拆到多個(gè)Region服務(wù)器
          每個(gè)Region服務(wù)器存儲(chǔ)10-1000個(gè)Region

          元數(shù)據(jù)表,又名.META.表,存儲(chǔ)了RegionRegion服務(wù)器的映射關(guān)系
          當(dāng)HBase表很大時(shí), .META.表也會(huì)被分裂成多個(gè)Region
          根數(shù)據(jù)表,又名-ROOT-表,記錄所有元數(shù)據(jù)的具體位置
          -ROOT-表只有唯一一個(gè)Region,名字是在程序中被寫(xiě)死的
          Zookeeper文件記錄了-ROOT-表的位置


          客戶(hù)端訪(fǎng)問(wèn)數(shù)據(jù)時(shí)的“三級(jí)尋址”

          為了加速尋址,客戶(hù)端會(huì)緩存位置信息,同時(shí),需要解決緩存失效問(wèn)題

          尋址過(guò)程客戶(hù)端只需要詢(xún)問(wèn)Zookeeper服務(wù)器,不需要連接Master服務(wù)器

          3、HBase的三層結(jié)構(gòu)中各層次的名稱(chēng)和作用

          層次

          名稱(chēng)

          作用

          第一層

          Zookeper文件

          記錄了-ROOT-表的位置信息

          第二層

          -ROOT-

          記錄了.META.表的Region位置信息

          -ROOT-表只能有一個(gè)Region。通過(guò)-ROOT-表,就可以訪(fǎng)問(wèn).META.表中的數(shù)據(jù)

          第三層

          .META.

          記錄了用戶(hù)數(shù)據(jù)表的Region位置信息,.META.表可以有多個(gè)Region,保存了HBase中所有用戶(hù)數(shù)據(jù)表的Region位置信息

          四、HBase運(yùn)行機(jī)制
          1、HBase系統(tǒng)架構(gòu)


          (1、客戶(hù)端包含訪(fǎng)問(wèn)HBase的接口,同時(shí)在緩存中維護(hù)著已經(jīng)訪(fǎng)問(wèn)過(guò)的Region位置信息,用來(lái)加快后續(xù)數(shù)據(jù)訪(fǎng)問(wèn)過(guò)程

          (2、Zookeeper可以幫助選舉出一個(gè)Master作為集群的總管,并保證在任何時(shí)刻總有唯一一個(gè)Master在運(yùn)行,這就避免了Master的“單點(diǎn)失效”問(wèn)題
          Zookeeper是一個(gè)很好的集群管理工具,被大量用于分布式計(jì)算,提供配置維護(hù)、域名服務(wù)、分布式同步、組服務(wù)等。

          (3. Master
          主服務(wù)器Master主要負(fù)責(zé)表和Region的管理工作:
          管理用戶(hù)對(duì)表的增加、刪除、修改、查詢(xún)等操作
          實(shí)現(xiàn)不同Region服務(wù)器之間的負(fù)載均衡
          Region分裂或合并后,負(fù)責(zé)重新調(diào)整Region的分布
          對(duì)發(fā)生故障失效的Region服務(wù)器上的Region進(jìn)行遷移
          (4. Region服務(wù)器
          Region服務(wù)器是HBase中最核心的模塊,負(fù)責(zé)維護(hù)分配給自己的Region,并響應(yīng)用戶(hù)的讀寫(xiě)請(qǐng)求
          2、Region


          (1、用戶(hù)讀寫(xiě)數(shù)據(jù)過(guò)程
          用戶(hù)寫(xiě)入數(shù)據(jù)時(shí),被分配到相應(yīng)Region服務(wù)器去執(zhí)行
          用戶(hù)數(shù)據(jù)首先被寫(xiě)入到MemStoreHlog
          只有當(dāng)操作寫(xiě)入Hlog之后,commit()調(diào)用才會(huì)將其返回給客戶(hù)端
          當(dāng)用戶(hù)讀取數(shù)據(jù)時(shí),Region服務(wù)器會(huì)首先訪(fǎng)問(wèn)MemStore緩存,如果找不到,再去磁盤(pán)上面的StoreFile中尋找
          (2、緩存的刷新
          系統(tǒng)會(huì)周期性地把MemStore緩存里的內(nèi)容刷寫(xiě)到磁盤(pán)的StoreFile文件中,清空緩存,并在Hlog里面寫(xiě)入一個(gè)標(biāo)記、
          每次刷寫(xiě)都生成一個(gè)新的StoreFile文件,因此,每個(gè)Store包含多個(gè)StoreFile文件

          每個(gè)Region服務(wù)器都有一個(gè)自己的HLog文件,每次啟動(dòng)都檢查該文件,確認(rèn)最近一次執(zhí)行緩存刷新操作之后是否發(fā)生新的寫(xiě)入操作;如果發(fā)現(xiàn)更新,則先寫(xiě)入MemStore,再刷寫(xiě)到StoreFile,最后刪除舊的Hlog文件,開(kāi)始為用戶(hù)提供服務(wù)
          (3、StroreFile的合并
          每次刷寫(xiě)都生成一個(gè)新的StoreFile,數(shù)量太多,影響查找速度
          調(diào)用Store.compact()把多個(gè)合并成一個(gè)
          合并操作比較耗費(fèi)資源,只有數(shù)量達(dá)到一個(gè)閾值才啟動(dòng)合并
          3、Store工作原理
          StoreRegion服務(wù)器的核心
          多個(gè)StoreFile合并成一個(gè)
          觸發(fā)分裂操作,1個(gè)父Region被分裂成兩個(gè)子Region
          單個(gè)StoreFile過(guò)大時(shí),又
          4、HLog工作原理
          分布式環(huán)境必須要考慮系統(tǒng)出錯(cuò)。HBase采用HLog保證系統(tǒng)恢復(fù)
          HBase系統(tǒng)為每個(gè)Region服務(wù)器配置了一個(gè)HLog文件,它是一種預(yù)寫(xiě)式日志(WriteAhead Log
          用戶(hù)更新數(shù)據(jù)必須首先寫(xiě)入日志后,才能寫(xiě)入MemStore緩存,并且,直到MemStore緩存內(nèi)容對(duì)應(yīng)的日志已經(jīng)寫(xiě)入磁盤(pán),該緩存內(nèi)容才能被刷寫(xiě)到磁盤(pán)

          Zookeeper會(huì)實(shí)時(shí)監(jiān)測(cè)每個(gè)Region服務(wù)器的狀態(tài),當(dāng)某個(gè)Region服務(wù)器發(fā)生故障時(shí),Zookeeper會(huì)通知Master
          Master首先會(huì)處理該故障Region服務(wù)器上面遺留的HLog文件,這個(gè)遺留的HLog文件中包含了來(lái)自多個(gè)Region對(duì)象的日志記錄
          系統(tǒng)會(huì)根據(jù)每條日志記錄所屬的Region對(duì)象對(duì)HLog數(shù)據(jù)進(jìn)行拆分,分別放到相應(yīng)Region對(duì)象的目錄下,然后,再將失效的Region重新分配到可用的Region服務(wù)器中,并把與該Region對(duì)象相關(guān)的HLog日志記錄也發(fā)送給相應(yīng)的Region服務(wù)器
          Region服務(wù)器領(lǐng)取到分配給自己的Region對(duì)象以及與之相關(guān)的HLog日志記錄以后,會(huì)重新做一遍日志記錄中的各種操作,把日志記錄中的數(shù)據(jù)寫(xiě)入到MemStore緩存中,然后,刷新到磁盤(pán)的StoreFile文件中,完成數(shù)據(jù)恢復(fù)
          共用日志優(yōu)點(diǎn):提高對(duì)表的寫(xiě)操作性能;缺點(diǎn):恢復(fù)時(shí)需要分拆日志
          五、HBase性能
          1、行鍵(RowKey)

          行鍵是按照字典序存儲(chǔ),因此,設(shè)計(jì)行鍵時(shí),要充分利用這個(gè)排序特點(diǎn),將經(jīng)常一起讀取的數(shù)據(jù)存儲(chǔ)到一塊,將最近可能會(huì)被訪(fǎng)問(wèn)的數(shù)據(jù)放在一塊。

          舉個(gè)例子:如果最近寫(xiě)入HBase表中的數(shù)據(jù)是最可能被訪(fǎng)問(wèn)的,可以考慮將時(shí)間戳作為行鍵的一部分,由于是字典序排序,所以可以使用Long.MAX_VALUE- timestamp作為行鍵,這樣能保證新寫(xiě)入的數(shù)據(jù)在讀取時(shí)可以被快速命中。

          InMemory:創(chuàng)建表的時(shí)候,可以通過(guò)HColumnDescriptor.setInMemory(true)將表放到Region服務(wù)器的緩存中,保證在讀取的時(shí)候被cache命中。

          Max Version:創(chuàng)建表的時(shí)候,可以通過(guò)HColumnDescriptor.setMaxVersions(int maxVersions)設(shè)置表中數(shù)據(jù)的最大版本,如果只需要保存最新版本的數(shù)據(jù),那么可以設(shè)置setMaxVersions(1)

          Time To Live創(chuàng)建表的時(shí)候,可以通過(guò)HColumnDescriptor.setTimeToLive(inttimeToLive)設(shè)置表中數(shù)據(jù)的存儲(chǔ)生命期,過(guò)期數(shù)據(jù)將自動(dòng)被刪除,例如如果只需要存儲(chǔ)最近兩天的數(shù)據(jù),那么可以設(shè)置setTimeToLive(2* 24 * 60 * 60)

          2、HBaseMaster默認(rèn)基于WebUI服務(wù)端口為60010HBase region服務(wù)器默認(rèn)基于WebUI服務(wù)端口為60030.如果master運(yùn)行在名為master.foo.com的主機(jī)中,mater的主頁(yè)地址就是http://master.foo.com:60010,用戶(hù)可以通過(guò)Web瀏覽器輸入這個(gè)地址查看該頁(yè)面
          可以查看HBase集群的當(dāng)前狀態(tài)
          3、NoSQL區(qū)別于關(guān)系型數(shù)據(jù)庫(kù)的一點(diǎn)就是NoSQL不使用SQL作為查詢(xún)語(yǔ)言,至于為何在NoSQL數(shù)據(jù)存儲(chǔ)HBase上提供SQL接口

          易使用,減少編碼

          4、HBase只有一個(gè)針對(duì)行健的索引

          訪(fǎng)問(wèn)HBase表中的行,只有三種方式:

          通過(guò)單個(gè)行健訪(fǎng)問(wèn)
          通過(guò)一個(gè)行健的區(qū)間來(lái)訪(fǎng)問(wèn)
          全表掃描

          總結(jié):
          1、HBase數(shù)據(jù)庫(kù)是BigTable的開(kāi)源實(shí)現(xiàn),和BigTable一樣,支持大規(guī)模海量數(shù)據(jù),分布式并發(fā)數(shù)據(jù)處理效率極高,易于擴(kuò)展且支持動(dòng)態(tài)伸縮,適用于廉價(jià)設(shè)備
          2、HBase可以支持NativeJava APIHBaseShellThriftGatewayHive等多種訪(fǎng)問(wèn)接口,可以根據(jù)具體應(yīng)用場(chǎng)合選擇相應(yīng)訪(fǎng)問(wèn)方式
          3、HBase實(shí)際上就是一個(gè)稀疏、多維、持久化存儲(chǔ)的映射表,它采用行鍵、列鍵和時(shí)間戳進(jìn)行索引,每個(gè)值都是未經(jīng)解釋的字符串。
          4、HBase采用分區(qū)存儲(chǔ),一個(gè)大的表會(huì)被分拆許多個(gè)Region,這些Region會(huì)被分發(fā)到不同的服務(wù)器上實(shí)現(xiàn)分布式存儲(chǔ)
          5、HBase的系統(tǒng)架構(gòu)包括客戶(hù)端、Zookeeper服務(wù)器、Master主服務(wù)器、Region服務(wù)器。客戶(hù)端包含訪(fǎng)問(wèn)HBase的接口;Zookeeper服務(wù)器負(fù)責(zé)提供穩(wěn)定可靠的協(xié)同服務(wù);Master主服務(wù)器主要負(fù)責(zé)表和Region的管理工作;Region服務(wù)器負(fù)責(zé)維護(hù)分配給自己的Region,并響應(yīng)用戶(hù)的讀寫(xiě)請(qǐng)求

          posted @ 2017-07-19 22:24 鴻雁 閱讀(254) | 評(píng)論 (0)編輯 收藏

          在python中獲取mac和ip地址

          python 獲得本機(jī)MAC地址:
          import uuid
               def get_mac_address():
               mac=uuid.UUID(int=uuid.getnode()).hex[-12:]
               return ":".join([mac[e:e+2] for e in range(0,11,2)])


          python獲取IP的方法:使用socket

          import socket

          myname=socket.getfqdn(socket.gethostname( ))
              myaddr=socket.gethostbyname(myname)
              print(myname)
              print(myaddr)

          posted @ 2017-05-15 23:26 鴻雁 閱讀(254) | 評(píng)論 (0)編輯 收藏

          Spring—Quartz定時(shí)調(diào)度CronTrigger時(shí)間配置格式說(shuō)明與實(shí)例

          spring中使用Quartz時(shí) 時(shí)間配置例子:

          <!-- 定義調(diào)用對(duì)象和調(diào)用對(duì)象的方法 end   -->
          <!-- 定義調(diào)用時(shí)間 begin -->
          <bean id="realweatherTime" class="org.springframework.scheduling.quartz.CronTriggerBean">
          <property name="jobDetail">
          <ref bean="realweatherTask" />
          </property>
          <property name="cronExpression">
          <value>0 10/30 * * * ?</value><!-- 表示每小時(shí)的10,40時(shí)執(zhí)行任務(wù) -->
          </property>
          </bean>
          <!-- 定義調(diào)用時(shí)間 end   -->


          <!-- 定義調(diào)用對(duì)象和調(diào)用對(duì)象的方法 end   -->
          <!-- 定義調(diào)用時(shí)間 begin -->
          <bean id="weatherTime" class="org.springframework.scheduling.quartz.CronTriggerBean">
          <property name="jobDetail">
          <ref bean="weatherTask" />
          </property>
          <property name="cronExpression">
          <!--  <value>0 30 8,13 * * ?</value>  --><!-- 表示每天的8:30和13:30時(shí)執(zhí)行任務(wù) -->
          <value>0 0,30 0-23 * * ?</value><!---表示每天從0-23時(shí)中每時(shí)的整點(diǎn)或半點(diǎn)執(zhí)行任務(wù)->
          </property>
          </bean>

          <!-- 定義調(diào)用時(shí)間 end   -->1、   CronTrigger時(shí)間格式配置說(shuō)明

          CronTrigger配置格式:

          格式: [秒] [分] [小時(shí)] [日] [月] [周] [年]

          序號(hào)

          說(shuō)明

          是否必填

          允許填寫(xiě)的值

          允許的通配符

          1

          0-59 

          , - * /

          2

          0-59

          , - * /

          3

          小時(shí)

          0-23

          , - * /

          4

          1-31

          , - * ? / L W

          5

          1-12 or JAN-DEC

          , - * /

          6

          1-7 or SUN-SAT

          , - * ? / L #

          7

          empty 或 1970-2099

          , - * /

          通配符說(shuō)明:

          :表示所有值. 例如:在分的字段上設(shè)置 "*",表示每一分鐘都會(huì)觸發(fā)。
          ? 
          :表示不指定值。使用的場(chǎng)景為不需要關(guān)心當(dāng)前設(shè)置這個(gè)字段的值。例如:要在每月的10號(hào)觸發(fā)一個(gè)操作,但不關(guān)心是周幾,所以需要周位置的那個(gè)字段設(shè)置為"?" 具體設(shè)置為 0 0 0 10 * ?
          - 
          :表示區(qū)間。例如 在小時(shí)上設(shè)置 "10-12",表示 10,11,12點(diǎn)都會(huì)觸發(fā)。

          , :表示指定多個(gè)值,例如在周字段上設(shè)置 "MON,WED,FRI" 表示周一,周三和周五觸發(fā)
          :用于遞增觸發(fā)。如在秒上面設(shè)置"5/15" 表示從5秒開(kāi)始,每增15秒觸發(fā)(5,20,35,50)。 在月字段上設(shè)置'1/3'所示每月1號(hào)開(kāi)始,每隔三天觸發(fā)一次。
          L :表示最后的意思。在日字段設(shè)置上,表示當(dāng)月的最后一天(依據(jù)當(dāng)前月份,如果是二月還會(huì)依據(jù)是否是潤(rùn)年[leap]), 在周字段上表示星期六,相當(dāng)于"7"或"SAT"。如果在"L"前加上數(shù)字,則表示該數(shù)據(jù)的最后一個(gè)。

          例如在周字段上設(shè)置"6L"這樣的格式,則表示“本月最后一個(gè)星期五"

          W :表示離指定日期的最近那個(gè)工作日(周一至周五). 例如在日字段上設(shè)置"15W",表示離每月15號(hào)最近的那個(gè)工作日觸發(fā)。如果15號(hào)正好是周六,則找最近的周五(14號(hào))觸發(fā), 如果15號(hào)是周未,則找最近的下周一(16號(hào))觸發(fā).如果15號(hào)正好在工作日(周一至周五),則就在該天觸發(fā)。如果指定格式為 "1W",它則表示每月1號(hào)往后最近的工作日觸發(fā)。如果1號(hào)正是周六,則將在3號(hào)下周一觸發(fā)。(注,"W"前只能設(shè)置具體的數(shù)字,不允許區(qū)間"-").

          'L'和 'W'可以一組合使用。如果在日字段上設(shè)置"LW",則表示在本月的最后一個(gè)工作日觸發(fā)

           

          # :序號(hào)(表示每月的第幾周星期幾),例如在周字段上設(shè)置"6#3"表示在每月的第三個(gè)周星期六.注意如果指定"6#5",正好第五周沒(méi)有星期六,則不會(huì)觸發(fā)該配置(用在母親節(jié)和父親節(jié)再合適不過(guò)了)

          周字段的設(shè)置,若使用英文字母是不區(qū)分大小寫(xiě)的 MON 與mon相同.

          常用示例:

          格式: [秒] [分] [小時(shí)] [日] [月] [周] [年]

          0 0 12 * * ?           每天12點(diǎn)觸發(fā) 
          0 15 10 ? * *          每天10點(diǎn)15分觸發(fā)
           
          0 15 10 * * ?          每天10點(diǎn)15分觸發(fā)
            
          0 15 10 * * ? *        每天10點(diǎn)15分觸發(fā)
            
          0 15 10 * * ? 2005     2005年每天10點(diǎn)15分觸發(fā)
           
          0 * 14 * * ?           每天下午的 2點(diǎn)到2點(diǎn)59分每分觸發(fā)
           
          0 0/5 14 * * ?         每天下午的 2點(diǎn)到2點(diǎn)59分(整點(diǎn)開(kāi)始,每隔5分觸發(fā)
          )  
          0 0/5 14,18 * * ?        每天下午的 18點(diǎn)到18點(diǎn)59分(整點(diǎn)開(kāi)始,每隔5分觸發(fā))

          0 0-5 14 * * ?            每天下午的 2點(diǎn)到2點(diǎn)05分每分觸發(fā) 
          0 10,44 14 ? 3 WED        3月分每周三下午的 2點(diǎn)10分和2點(diǎn)44分觸發(fā)
           
          0 15 10 ? * MON-FRI       從周一到周五每天上午的10點(diǎn)15分觸發(fā)
           
          0 15 10 15 * ?            每月15號(hào)上午10點(diǎn)15分觸發(fā)
           
          0 15 10 L * ?             每月最后一天的10點(diǎn)15分觸發(fā)
           
          0 15 10 ? * 6L            每月最后一周的星期五的10點(diǎn)15分觸發(fā)
           
          0 15 10 ? * 6L 2002-2005  從2002年到2005年每月最后一周的星期五的10點(diǎn)15分觸發(fā)

          0 15 10 ? * 6#3           每月的第三周的星期五開(kāi)始觸發(fā) 
          0 0 12 1/5 * ?            每月的第一個(gè)中午開(kāi)始每隔5天觸發(fā)一次
           
          0 11 11 11 11 ?           每年的11月11號(hào) 11點(diǎn)11分觸發(fā)(光棍節(jié))

          spring中使用Quartz時(shí) 時(shí)間配置例子:

          <!-- 定義調(diào)用對(duì)象和調(diào)用對(duì)象的方法 end   -->
          <!-- 定義調(diào)用時(shí)間 begin -->
          <bean id="realweatherTime" class="org.springframework.scheduling.quartz.CronTriggerBean">
          <property name="jobDetail">
          <ref bean="realweatherTask" />
          </property>
          <property name="cronExpression">
          <value>0 10/30 * * * ?</value><!-- 表示每小時(shí)的10,40時(shí)執(zhí)行任務(wù) -->
          </property>
          </bean>
          <!-- 定義調(diào)用時(shí)間 end   -->


          <!-- 定義調(diào)用對(duì)象和調(diào)用對(duì)象的方法 end   -->
          <!-- 定義調(diào)用時(shí)間 begin -->
          <bean id="weatherTime" class="org.springframework.scheduling.quartz.CronTriggerBean">
          <property name="jobDetail">
          <ref bean="weatherTask" />
          </property>
          <property name="cronExpression">
          <!--  <value>0 30 8,13 * * ?</value>  --><!-- 表示每天的8:30和13:30時(shí)執(zhí)行任務(wù) -->
          <value>0 0,30 0-23 * * ?</value><!---表示每天從0-23時(shí)中每時(shí)的整點(diǎn)或半點(diǎn)執(zhí)行任務(wù)->
          </property>
          </bean>
          <!-- 定義調(diào)用時(shí)間 end   -->


          posted @ 2017-04-29 12:01 鴻雁 閱讀(320) | 評(píng)論 (0)編輯 收藏

          主站蜘蛛池模板: 广宁县| 全椒县| 长子县| 山阳县| 彭水| 兴海县| 五河县| 扶风县| 家居| 平塘县| 昌图县| 永丰县| 衡东县| 汕头市| 宁国市| 商河县| 杭锦旗| 定州市| 怀柔区| 天水市| 河东区| 平江县| 芜湖市| 河津市| 美姑县| 九台市| 宜宾市| 会同县| 石景山区| 柳江县| 江源县| 太湖县| 惠东县| 五原县| 九龙城区| 汨罗市| 茶陵县| 南涧| 连南| 无锡市| 祁门县|