女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

兩億多用戶,六大業(yè)務場景,知乎AI用戶模型服務性能如何優(yōu)化?

電子工程師 ? 來源:工程師李察 ? 2019-01-05 11:06 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

用戶模型簡介

知乎 AI 用戶模型服務于知乎兩億多用戶,主要為首頁、推薦、廣告、知識服務、想法、關注頁等業(yè)務場景提供數據和服務,例如首頁個性化 Feed 的召回和排序、相關回答等用到的用戶長期興趣特征,問題路由、回答排序中用到的 TPR「作者創(chuàng)作權威度」,廣告定向投放用到的基礎屬性等。

主要功能

提供的數據和功能主要有:

用戶興趣:長期興趣、實時興趣、分類興趣、話題興趣、keyword 興趣、作者創(chuàng)作權威度等,

用戶 Embedding 表示:最近鄰用戶、人群劃分、特定用戶圈定等,

用戶社交屬性:用戶親密度、二度好友、共同好友、相似優(yōu)秀回答者等,

用戶實時屬性: LastN 行為、LastLogin 等,

用戶基礎屬性:用戶性別預測、年齡段計算、職業(yè)預估等。

服務架構

整體主要分為 Streaming / 離線計算、在線服務和 HBase 多集群同步三部分組成,下面將依次進行介紹。

用戶模型服務架構圖

Streaming / 離線計算

Streaming 計算主要涉及功能 LastRead、LastSearch、LastDisplay,實時話題/ Keyword 興趣、最后登錄時間、最后活躍的省市等。

用戶模型實時興趣計算邏輯圖

實時興趣的計算流程

相應日志獲取。從 CardshowLog、PageshowLog、QueryLog 中抽取<用戶,contentToken,actionType >等內容。

映射到對應的內容維度。對于問題、回答、文章、搜索分別獲取對應的 Topic 和 Keyword,搜索內容對應的 Topic。在 Redis 中用 contentToken 置換 contentId 后,請求 ContentProfile 獲取其對應話題和關鍵詞;對于 Query,調用 TopicMatch 服務,傳遞搜索內容給服務,服務返回其對應的 Topic;調用 Znlp 的 KeywordExtractorJar 包,傳遞搜索內容并獲得其對應的 Keyword 。

用戶-內容維度匯總。根據用戶的行為,在<用戶,topic,actionType>和<用戶,keyword,actionType>層面進行 groupBy 聚合匯總后,并以 hashmap 的格式存儲到 Redis,作為計算用戶實時興趣的基礎數據,按時間衰減系數 timeDecay 進行新舊興趣的 merge 后存儲。

計算興趣。在用戶的歷史基礎數據上,按一定的 decay 速度進行衰減,按威爾遜置信區(qū)間計算用戶興趣 score,并以 Sortedset 的格式存儲到 Redis。

關于興趣計算,已經優(yōu)化的地方主要是:如何快速的計算平滑參數 alpha 和 beta,如何 daily_update 平滑參數,以及用卡方計算置信度時,是否加入平滑參數等都會對最終的興趣分值有很大的影響,當 display 為 1 曝光數量不足的情況下,興趣 score 和 confidence 計算出現 的 bias 問題等。

在線服務

隨之知乎日益增加的用戶量,以及不斷豐富的業(yè)務場景和與之相對應出現的調用量上升等,對線上服務的穩(wěn)定性和請求時延要求也越來越高。 舊服務本身也存在一些問題,比如:

在線服務直連 HBase,當數據熱點的時候,造成某些 Region Server 的負載很高,P95 上升,輕者造成服務抖動,監(jiān)控圖偶發(fā)有「毛刺」現象,重者造成服務幾分鐘的不可用,需要平臺技術人員將 Region 從負載較高的 RegionServer 上移走。

離線任務每次計算完成后一次大批量同時寫入離線和在線集群,會加重 HBase 在線集群Region Server 的負載,增大 HBase get 請求的時延,從而影響線上服務穩(wěn)定性和 P95。

針對問題一,我們在原來的服務架構中增加緩存機制,以此來增強服務的穩(wěn)定型、減小 Region Server 的負載。

針對問題二,修改了離線計算和多集群數據同步的方式,詳見「HBase多集群存儲機制」部分。

Cache機制具體實現

沒有 Cache 機制時,所有的 get 和 batchGet 方法直接請求到 HBase,具體如下圖:

用戶模型服務請求序列圖

UserProfileServiceApp 啟動服務,將收到的請求交由 UserProfileServiceImpl 具體處理

UserProfileServiceImp 根據請求參數,調用 GetTranslator 將 UserProfileRequest.GetRequest 轉化成 HBase 中的 Get Object(在 Map 中維護每個 requestField 對應 HBase 中的 tablename,cf,column,prefix 等信息),以格式Map[String, util.List[(AvailField, Get)]]返回。

UserProfileServiceImp 用 Future 異步向 HBase 發(fā)送 get 請求,獲取到結果返回。

增加 Cache 機制的具體方法,在上面的第二步中,增加一個 CacheMap,用來維護 get 中 AvailField 對應 Cache 中的 key,key 的組成格式為:「 tablename 縮寫| columnfamily 縮寫| columnname 縮寫| rowkey 全寫」。這里使用的 Redis 數據結構主要有兩種,SortedSet 和 Key-Value對。服務端收到請求后先去轉化 requestField 為 Cache 中的 key,從 Cache 中獲取數據。對于沒有獲取到 requestField 的轉化成 GetObject,請求 HBase 獲取,將結果保存到 Cache 中并返回。

最終效果

用戶模型的訪問量大概為 100K QPS,每個請求轉化為多個 get 請求。 增加 Cache 前 get 請求的 P95 為30ms,增加 Cache 后降低到小于 15ms,Cache 命中率 90% 以上。

HBase 多集群存儲機制

離線任務和 Streaming 計算主要采用 Spark 計算實現, 結果保存到 HBase 的幾種方式:

方法一:每次一條

1. 每次寫進一條,調用 API 進行存儲的代碼如下:

valhbaseConn=ConnectionFactory.createConnection(hbaseConf)valtable=hbaseConn.getTable(TableName.valueOf("word"))x.foreach(value=>{varput=newPut(Bytes.toBytes(value.toString))put.addColumn(Bytes.toBytes("f1"),Bytes.toBytes("c1"),Bytes.toBytes(value.toString))table.put(put)})

方法二:批量寫入

2. 批量寫入 HBase,使用的 API:

/***{@inheritDoc}*@throwsIOException*/@Overridepublicvoidput(finalListputs)throwsIOException{getBufferedMutator().mutate(puts);if(autoFlush){flushCommits();}}

方法三:MapReduce 的 saveAsNewAPIHadoopDataset 方式寫入

3. saveAsNewAPIHadoopDataset 是通用的保存到 Hadoop 存儲系統的方法,調用 org.apache.hadoop.mapreduce.RecordWriter 實現。org.apache.hadoop.hbase.mapreduce.TableOutputFormat.TableRecordWriter 是其在 HBase 中的實現類。底層通過調用 hbase.client.BufferedMutator.mutate() 方式保存。

valrdd=sc.makeRDD(Array(1)).flatMap(_=>0to1000000)rdd.map(x=>{varput=newPut(Bytes.toBytes(x.toString))put.addColumn(Bytes.toBytes("f1"),Bytes.toBytes("c1"),Bytes.toBytes(x.toString))(newImmutableBytesWritable,put)}).saveAsHadoopDataset(jobConf)/***Writesakey/valuepairintothetable.*@throwsIOExceptionWhenwritingfails.*/@Overridepublicvoidwrite(KEYkey,Mutationvalue)throwsIOException{if(!(valueinstanceofPut)&&!(valueinstanceofDelete)){thrownewIOException("PassaDeleteoraPut");}mutator.mutate(value);}

方法四:BulkLoad 方式

4. BulkLoad 方式,創(chuàng)建 HFiles,調用 LoadIncrementalHFiles 作業(yè)將它們移到 HBase 表中。

首先需要根據表名 getRegionLocator 得到 RegionLocator,根據 RegionLocator 得到 partition,因為在 HFile 中是有序的所以,需要調用 rdd.repartitionAndSortWithinPartitions(partitioner) 將 rdd 重新排序。

HFileOutputFormat2.configureIncrementalLoad(job,table, regionLocator) 進行任務增量Load 到具體表的配置 實現并執(zhí)行映射( 并減少) 作業(yè),使用 HFileOutputFormat2 輸出格式將有序的放置或者 KeyValue 對象寫入HFile文件。Reduce階段通過調用 HFileOutputFormat2.configureIncrementalLoad 配置在場景后面。執(zhí)行LoadIncrementalHFiles 作業(yè)將 HFile 文件移動到系統文件。

staticvoidconfigureIncrementalLoad(Jobjob,Tabletable,RegionLocatorregionLocator,Class>cls)throwsIOException{Configurationconf=job.getConfiguration();job.setOutputKeyClass(ImmutableBytesWritable.class);job.setOutputValueClass(KeyValue.class);job.setOutputFormatClass(cls);//Basedontheconfiguredmapoutputclass,setthecorrectreducertoproperly//sorttheincomingvalues.if(KeyValue.class.equals(job.getMapOutputValueClass())){job.setReducerClass(KeyValueSortReducer.class);}elseif(Put.class.equals(job.getMapOutputValueClass())){job.setReducerClass(PutSortReducer.class);}elseif(Text.class.equals(job.getMapOutputValueClass())){job.setReducerClass(TextSortReducer.class);}else{LOG.warn("Unknownmapoutputvaluetype:"+job.getMapOutputValueClass());}conf.setStrings("io.serializations",conf.get("io.serializations"),MutationSerialization.class.getName(),ResultSerialization.class.getName(),KeyValueSerialization.class.getName());configurePartitioner(job,startKeys);//SetcompressionalgorithmsbasedoncolumnfamiliesconfigureCompression(table,conf);configureBloomType(table,conf);configureBlockSize(table,conf);configureDataBlockEncoding(table,conf);TableMapReduceUtil.addDependencyJars(job);TableMapReduceUtil.initCredentials(job);LOG.info("Incrementaltable"+table.getName()+"outputconfigured.");}publicstaticvoidconfigureIncrementalLoad(Jobjob,Tabletable,RegionLocatorregionLocator)throwsIOException{configureIncrementalLoad(job,table,regionLocator,HFileOutputFormat2.class);}valhFileLoader=newLoadIncrementalHFiles(conf)hFileLoader.doBulkLoad(hFilePath,newHTable(conf,table.getName))

將 HFile 文件 Bulk Load 到已存在的表中。 由于 HBase 的 BulkLoad 方式是繞過了 Write to WAL,Write to MemStore 及 Flush to disk 的過程,所以并不能通過 WAL 來進行一些復制數據的操作。 由于 Bulkload 方式還是對集群 RegionServer 造成很高的負載,最終采用方案三,下面是兩個集群進行數據同步。

存儲同步機制

技術選型 HBase 常見的 Replication 方法有 SnapShot、CopyTable/Export、BulkLoad、Replication、應用層并發(fā)讀寫等。 應用層并發(fā)讀寫 優(yōu)點:應用層可以自由靈活控制對 HBase寫入速度,打開或關閉兩個集群間的同步,打開或關閉兩個集群間具體到表或者具體到列簇的同步,對 HBase 集群性能的影響最小,缺點是增加了應用層的維護成本。 初期沒有更好的集群數據同步方式的時候,用戶模型和內容模型自己負責兩集群間的數據同步工作。

用戶模型存儲多機房同步架構圖

具體實現細節(jié)

第一步:定義用于在 Kafka 的 Producer 和 Consumer 中流轉的統一數據 Protobuf 格式

messageColumnValue{requiredbytesqualifier=1;......}messagePutMessage{requiredstringtablename=1;......}

第二步:發(fā)送需要同步的數據到 Kafka,(如果有必要,需要對數據做相應的格式處理),這里對數據的處理,有兩種方式。 第一種:如果程序中有統一的存儲到 HBase 的工具(另一個項目是使用自定義的 HBaseHandler,業(yè)務層面只生成 tableName,rowKey,columnFamily,column 等值,由 HBaseHandler 統一構建成 Put 對象,并保存 HBase 中),這種方式在業(yè)務層面改動較小,理論上可以直接用原來的格式發(fā)給 Kafka,但是如果 HBaseHandler 處理的格式和 PutMessage 格式有不符的地方,做下適配即可。

/***tableName:hbasetablename*rdd:RDD[(rowkey,family,column,value)]*/defconvert(tableName:String,rdd:RDD):RDD={rdd.map{case(rowKey:String,family:String,column:String,value:Array[Byte])=>valmessage=KafkaMessages.newBuilder()valcolumnValue=ColumnValue.newBuilder()columnValue.set......(rowKey,message.build().toByteArray)}}

第二種:程序在 RDD 中直接構建 HBase 的 Put 對象,調用 PairRDD 的 saveAsNewAPIHadoopDataset 方法保存到 HBase 中。此種情況,為了兼容已有的代碼,做到代碼和業(yè)務邏輯的改動最小,發(fā)送到 Kafka 時,需要將 Put 對象轉換為上面定義的 PutMessage Protobuf 格式,然后發(fā)送給 Kafka。

/***tableName:hbasetablenamne*rdd:RDD[(rowKey,put)]*/defconvert(tableName:String,familyNames:Array[String],rdd:RDD):RDD={rdd.map{case(_,put:Put)=>valmessage=PutMessage.newBuilder()for(familyName<-?familyNames){??????if(put.getFamilyMap().get(Bytes.toBytes(familyName))!=null){??????val?keyValueList?=?put.getFamilyMap()????????.asInstanceOf[java.util.ArrayList[KeyValue]].asScala????????for(?keyvalue?<-?keyValueList){??????????message.setRowkey(ByteString.copyFrom(keyvalue.getRow))????????......????????}????????message.setTablename(tableName)??????}????}????(null,?message.build().toByteArray)?}}

第三步:發(fā)送到 Kafka,不同的表發(fā)送到不同的 Topic,對每個 Topic 的消費做監(jiān)控。

/***發(fā)送rdd中的內容到brokers的指定topic中*tableName:hbasetablenamne*rdd:RDD[(rowKey,put)]*/defsend[T](brokers:String,rdd:RDD[(String,T)],topic:String)(implicitcTag:ClassTag[T]):Unit={rdd.foreachPartition(partitionOfRecords=>{valproducer=getProducer[T](brokers)partitionOfRecords.map(r=>newProducerRecord[String,T](topic,r._1,r._2)).foreach(m=>producer.send(m))producer.close()})}

第四步:另啟動 Streaming Consumer 或者服務消費 Kafka 中內容,將 putMessage 的 Protobuf 格式轉成 HBase 的 put 對象,同時寫入到在線 HBase 集群中。 Streaming 消費Kafka ,不同的表發(fā)送到不同的 Topic,對每個 Topic 的消費做監(jiān)控。

valtoHBaseTagsTopic=validKafkaStreamTagsTopic.map{record=>valtableName_r=record.getTablename()valput=newPut(record.getRowkey.toByteArray)for(cv<-?record.getColumnsList)?{??????????put.addColumn(record.getFamily.toByteArray)??????????......????????}????????if(put.isEmpty){??????????(new?ImmutableBytesWritable(),?null)????????}else{??????????(new?ImmutableBytesWritable(),?put)????????}????}.filter(_._2!=null)????if(!isClean)?{??????toHbaseTagsTopic.foreachRDD?{?rdd?=>rdd.saveAsNewAPIHadoopDataset(AccessUtils.createOutputTableConfiguration(constants.Constants.NAMESPACE+":"+constants.Constants.TAGS_TOPIC_TABLE_NAME))}}

如下為另一種啟動服務消費 Kafka 的方式。

valconsumer=newKafkaConsumer[String,Array[Byte]](probs)consumer.subscribe(topics)valrecords=consumer.poll(100)for(p<-?records.partitions)?{???val?recordsOfPartition?=?records.records(p)???recordsOfPartition.foreach?{?r?=>Try(KafkaMessages.parseFrom(r.value()))match{caseSuccess(record)=>valtableName=record.getTableNameif(validateTables.contains(tableName)){valmessageType=record.getType......try{valcolumns=record.getColumnsList.map(c=>(c.getColumn,c.getValue.toByteArray)).toArrayHBaseHandler.write(tableName)......}catch{caseex:Throwable=>LOG.error("writehbasefail")HaloClient.increment(s"content_write_hbase_fail")}}else{LOG.error(s"table$tableNameisvalid")}}}//updateoffsetvallastOffset=recordsOfPartition.get(recordsOfPartition.size-1).offset()consumer.commitSync(java.util.Collections.singletonMap(p,newOffsetAndMetadata(lastOffset+1)))}

結語

最后,目前采用的由應用控制和管理在線離線集群的同步機制,在隨著平臺多機房項目的推動下,平臺將推出 HBase 的統一同步機制 HRP (HBase Replication Proxy),屆時業(yè)務部門可以將更多的時間和精力集中在模型優(yōu)化層面。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯系本站處理。 舉報投訴
  • API
    API
    +關注

    關注

    2

    文章

    1613

    瀏覽量

    64013
  • AI
    AI
    +關注

    關注

    88

    文章

    35109

    瀏覽量

    279587
  • 模型
    +關注

    關注

    1

    文章

    3519

    瀏覽量

    50411

原文標題:兩億多用戶,六大業(yè)務場景,知乎AI用戶模型服務性能如何優(yōu)化?

文章出處:【微信號:rgznai100,微信公眾號:rgznai100】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    海思SD3403邊緣計算AI數據訓練概述

    AI數據訓練:基于用戶特定應用場景用戶采集照片或視頻,通過AI數據訓練工程師**(用戶公司**
    發(fā)表于 04-28 11:11

    DevEco Studio AI輔助開發(fā)工具大升級功能 鴻蒙應用開發(fā)效率再提升

    使用結合機制和反饋優(yōu)化手段,有效融合檢索模塊和生成模塊,以及不斷提升RAG系統性能: 1、結合機制: (1) 概率加權:通過對檢索到的文檔分配權重,影響生成模型的輸出。 (2) 多文檔處理:結合多篇相關文檔
    發(fā)表于 04-18 14:43

    首創(chuàng)開源架構,天璣AI開發(fā)套件讓端側AI模型接入得心應手

    科正將AI能力體系化并賦能終端生態(tài)。 大會上,聯發(fā)科定義了“智能體化用戶體驗”的五大特征:主動及時、你懂你、互動協作、學習進化和專屬隱私信息守護。這五大特征需要跨越從芯片、模型、應
    發(fā)表于 04-13 19:52

    硅基覺醒已至前夜,聯發(fā)科攜手生態(tài)加速智能體化用戶體驗時代到來

    推動AI從“能用”到“好用”,關鍵不只是算力升級,更在于工具鏈與生態(tài)的協同完善。在MDDC 2025大會上,聯發(fā)科首度集成發(fā)布AI+游戲全場景支持平臺:Neuron Studio聚焦AI
    發(fā)表于 04-13 19:51

    鴻蒙應用元服務開發(fā)-Account Kit獲取華為賬號用戶信息概述

    詳細接入體驗可參考Account Kit提供的SampleCode示例工程。 典型場景: 1、元服務需要完善用戶頭像信息,參見獲取頭像。 2、元服務提供的
    發(fā)表于 04-02 11:10

    小程序開發(fā)必須知道的5個技巧:提升效率與用戶體驗的權威指南

    精準定位核心場景。 需求分析:明確目標用戶痛點,如電商類小程序需優(yōu)先優(yōu)化購物車與支付流程,而非復雜營銷工具。 模塊化開發(fā):通過自定義組件封裝高頻功能(如分享按鈕、客服入口),提升代碼復用率與維護效率
    發(fā)表于 03-14 14:51

    阿里云上線DeepSeek六大模型,贈送百萬免費tokens

    DeepSeek-R1-Distill-Qwen-32B、14B、7B和1.5B,共計款。 為了慶祝這一重要里程碑,阿里云決定向所有用戶贈送DeepSeek-R1和DeepSeek-V3
    的頭像 發(fā)表于 02-10 11:03 ?1028次閱讀

    deepin UOS AI接入DeepSeek-R1模型

    DeepSeek-R1 模型自發(fā)布以來吸引了眾多用戶關注,為了讓 deepin 用戶更好地體驗這一前沿技術,UOS AI 現已適配接入 DeepSeek-R1 端側
    的頭像 發(fā)表于 02-08 09:52 ?1064次閱讀

    【「基于大模型的RAG應用開發(fā)與優(yōu)化」閱讀體驗】+第一章初體驗

    機制。 《基于大模型的RAG應用開發(fā)與優(yōu)化》第一章以清晰的邏輯框架,幫助讀者建立對大模型與RAG的全局認知。通過剖析技術原理、優(yōu)勢與挑戰(zhàn),作者為后續(xù)章節(jié)的實踐內容奠定了基礎。對于開發(fā)者而言,掌握RAG技術不僅是提升
    發(fā)表于 02-07 10:42

    前端性能優(yōu)化:提升用戶體驗的關鍵策略

    在互聯網飛速發(fā)展的今天,用戶對于網頁的加載速度和響應性能要求越來越高。前端性能優(yōu)化成為了提升用戶體驗、增強網站競爭力的關鍵策略。一個
    的頭像 發(fā)表于 01-22 10:08 ?480次閱讀

    HarmonyOS Web開發(fā)性能優(yōu)化指導

    體驗,實現商業(yè)目標。通過文章介紹的幾種優(yōu)化方法,開發(fā)者可以改善頁面加載速度,提升用戶體驗,增加頁面瀏覽量,提高應用的活躍度和用戶粘性。只有不斷優(yōu)化頁面加載速度,才能更好地滿足
    發(fā)表于 12-06 08:41

    中國生成式AI用戶突破2.3

    近日,根據最新發(fā)布的《生成式人工智能應用發(fā)展報告〔2024〕》數據顯示,我國生成式人工智能產品的用戶群體規(guī)模已經顯著擴大。截至今年月底,使用生成式人工智能產品的用戶數量已超過兩億三千
    的頭像 發(fā)表于 12-02 10:05 ?683次閱讀

    正式公布三季度財報:月活躍用戶數穩(wěn)步增長

    近日,公司正式公布了其2024年第三季度的業(yè)績報告,展示了公司在該季度的經營成果。 據報告顯示,盡管在第三季度的營收出現了同比下降,具體數字為下降17.32%至8.45
    的頭像 發(fā)表于 11-27 10:44 ?1221次閱讀

    釘釘重磅升級:六大場景AI助理正式上線

    上線的“精選AI助理”涵蓋了六大關鍵場景,包括工單助理、Excel助理、法務助理等。這些AI助理通過智能化的手段,能夠幫助企業(yè)解決在日常運營中遇到的各種問題,例如快速處理工單、
    的頭像 發(fā)表于 11-14 13:50 ?631次閱讀

    AI模型性能優(yōu)化方法

    AI模型性能優(yōu)化是一個復雜而關鍵的任務,涉及多個方面和策略。以下是一些主要的性能優(yōu)化方法:
    的頭像 發(fā)表于 10-23 15:01 ?2410次閱讀