实时搜索: mapreduce有几个reduce

mapreduce有几个reduce

710条评论 3850人喜欢 4787次阅读 273人点赞
3.下列有关于大数据技术或计算模式及其代表产品有误的是()。
A. MapReduce是针对大规模数据的批量处理的代表产品。
B.HDFS是针对百度分布式文件系统GFS的开源实现,是分布式文件系统,提供了
在廉价服务器集群中进行大规模分布式文件存储的能力。
C. HBase:提供高可靠性、高性能、分布式的行式数据库,是谷歌 BigTable的开
源实现。
D. Zookeeper:针对谷歌 Chubby的一个开源实现,是高效可靠的系统工作系统 ...

一个MapReduce程序中可以执行多个map任务或reduce任务吗: 根据你的描述: 先有map然后redcue,但是面对多个job,map和redcue是同时进行的 具体可参考:这里面讲的还是比较全的 mapreduce学习指导及疑难解惑汇总

mapreduce中 job作业的reduce任务个数怎么确定: MapReduce作业提交源码分析
我们在编写MapReduce程序的时候,首先需要编写Map函数和Reduce函数。完成mapper和reducer的编写后,进行Job的配置;Job配置完成后,调用Job.submit()方法完成作业的提交。那我们思考一下,Job最终如何完成作业(job)的提交呢看粗略想一下,Job必然需要通过某种方式连接到JobTracker,因为只有这样才能将job提交到JobTracker上进行调度执行。还需要考虑一下,我们自己编写的mapper和reducer,即Jar文件如何传送到JobTracker上呢看其中有一种最简单也比较直观的方法,直接通过socket传输给JobTracker,由JobTracker再传输给TaskTracker(注意:MapReduce并没有采用这种方法)。第三个需要考虑的内容是,JobTracker如何将用户作业的配置转化成map task和reduce task。下面我们来分析一下MapReduce这些功能的实现。
首先在class Job内部通过JobClient完成作业的提交,最终由JobClient完成与JobTracker的交互功能。在JobClient的构造函数中,通过调用RPC完成与JobTracker连接的建立。
完成建立后,JobClient首先确定job相关文件的存放位置(我们上面提到mapreduce没有采用将jar即其他文件传输给JobTracker的方式,而是将这些文件保存到HDFS当中,并且可以根据用户的配置存放多份)。

mapreduce 输入和输出有多个目录: 1.MapReduce多路径输入
1.1FileInputFormat.addInputPath(s)
FileInputFormat.addInputPath()是我们最常用的设置MapReduce输入路径的方法了。其实,FileInputFormat有两个这样的方法:

[html] view plain copy
static void addInputPath(Job job, Path path)

static void addInputPaths(Job job, String commaSeperatedPaths)

addInputPath()只能指定一个路径,如果要想添加多个路径需要多次调用该方法:

[java] view plain copy
FileInputFormat.addInputPath(job, new Path(args[0]));
FileInputFormat.addInputPath(job, new Path(args[1]));
FileInputFormat.addInputPath(job, new Path(args[2]));

addInputPaths()可以指定多条路径,而这多条路径是用“,”分隔的一个字符串:

[java] view plain copy
String paths = strings[0] + "," + strings[1];
FileInputFormat.addInputPaths(job, paths);

如何实现mapreduce计算框架以有效实现迭代:   MapReduce从出现以来,已经成为Apache Hadoop计算范式的扛鼎之作。它对于符合其设计的各项工作堪称完美:大规模日志处理,ETL批处理操作等。

  随着Hadoop使用范围的不断扩大,人们已经清楚知道MapReduce不是所有计算的最佳框架。Hadoop 2将资源管理器YARN作为自己的顶级组件,为其他计算引擎的接入提供了可能性。如Impala等非MapReduce架构的引入,使平台具备了支持交互式SQL的能力。

  今天,Apache Spark是另一种这样的替代,并且被称为是超越MapReduce的通用计算范例。也许您会好奇:MapReduce一直以来已经这么有用了,怎么能突然被取代?毕竟,还有很多ETL这样的工作需要在Hadoop上进行,即使该平台目前也已经拥有其他实时功能。

  值得庆幸的是,在Spark上重新实现MapReduce一样的计算是完全可能的。它们可以被更简单的维护,而且在某些情况下更快速,这要归功于Spark优化了刷写数据到磁盘的过程。Spark重新实现MapReduce编程范式不过是回归本源。Spark模仿了Scala的函数式编程风格和API。而MapReduce的想法来自于函数式编程语言LISP。

  尽管Spark的主要抽象是RDD(弹性分布式数据集),实现了Map,reduce等操作,但这些都不是Hadoop的Mapper或Reducer API的直接模拟。这些转变也往往成为开发者从Mapper和Reducer类平行迁移到Spark的绊脚石。

  与Scala或Spark中经典函数语言实现的map和reduce函数相比,原有Hadoop提供的Mapper和Reducer API 更灵活也更复杂。这些区别对于习惯了MapReduce的开发者而言也许并不明显,下列行为是针对Hadoop的实现而不是MapReduce的抽象概念:
  · Mapper和Reducer总是使用键值对作为输入输出。
  · 每个Reducer按照Key对Value进行reduce。
  · 每个Mapper和Reducer对于每组输入可能产生0个,1个或多个键值对。
  · Mapper和Reducer可能产生任意的keys和values,而不局限于输入的子集和变换。
  Mapper和Reducer对象的生命周期可能横跨多个map和reduce操作。它们支持setup和cleanup方法,在批量记录处理开始之前和结束之后被调用。

  本文将简要展示怎样在Spark中重现以上过程,您将发现不需要逐字翻译Mapper和Reducer!

  作为元组的键值对
  假定我们需要计算大文本中每一行的长度,并且报告每个长度的行数。在HadoopMapReduce中,我们首先使用一个Mapper,生成为以行的长度作为key,1作为value的键值对。
  public class LineLengthMapper extends
  Mapper<LongWritable, Text, IntWritable, IntWritable> {
  @Override
  protected void map(LongWritable lineNumber, Text line, Context context)
  throws IOException, InterruptedException {
  context.write(new IntWritable(line.getLength()), new IntWritable(1));
  }
  }

  值得注意的是Mappers和Reducers只对键值对进行操作。所以由TextInputFormat提供输入给LineLengthMapper,实际上也是以文本中位置为key(很少这么用,但是总是需要有东西作为Key),文本行为值的键值对。

  与之对应的Spark实现:

  lines.map(line => (line.length, 1))

  Spark中,输入只是String构成的RDD,而不是key-value键值对。Spark中对key-value键值对的表示是一个Scala的元组,用(A,B)这样的语法来创建。上面的map操作的结果是(Int,Int)元组的RDD。当一个RDD包含很多元组,它获得了多个方法,如reduceByKey,这对再现MapReduce行为将是至关重要的。

  Reduce
  reduce()与reduceBykey()
  统计行的长度的键值对,需要在Reducer中对每种长度作为key,计算其行数的总和作为value。
  public class LineLengthReducer extends
  Reducer<IntWritable, IntWritable, IntWritable, IntWritable> {
  @Override
  protected void reduce(IntWritable length, Iterable<IntWritable> counts,
  Context context) throws IOException, InterruptedException {
  int sum = 0;
  for (IntWritable count : counts) {
  sum += count.get();
  }
  context.write(length, new IntWritable(sum));
  }
  }

  Spark中与上述Mapper,Reducer对应的实现只要一行代码:
  val lengthCounts = lines.map(line => (line.length, 1)).reduceByKey(_ + _)

  Spark的RDD API有个reduce方法,但是它会将所有key-value键值对reduce为单个value。这并不是Hadoop MapReduce的行为,Spark中与之对应的是ReduceByKey。

  另外,Reducer的Reduce方法接收多值流,并产生0,1或多个结果。而reduceByKey,它接受的是一个将两个值转化为一个值的函数,在这里,就是把两个数字映射到它们的和的简单加法函数。此关联函数可以被调用者用来reduce多个值到一个值。与Reducer方法相比,他是一个根据Key来Reduce Value的更简单而更精确的API。
  Mapper
  map() 与 flatMap()
  现在,考虑一个统计以大写字母开头的单词的个数的算法。对于每行输入文本,Mapper可能产生0个,1个或多个键值对。
  public class CountUppercaseMapper extends
  Mapper<LongWritable, Text, Text, IntWritable> {
  @Override
  protected void map(LongWritable lineNumber, Text line, Context context)
  throws IOException, InterruptedException {
  for (String word : line.toString().split(" ")) {
  if (Character.isUpperCase(word.charAt(0))) {
  context.write(new Text(word), new IntWritable(1));
  }
  }
  }
  }

  Spark对应的写法:
  lines.flatMap(
  _.split(" ").filter(word => Character.isUpperCase(word(0))).map(word => (word,1))
  )
  简单的Spark map函数不适用于这种场景,因为map对于每个输入只能产生单个输出,但这个例子中一行需要产生多个输出。所以,和MapperAPI支持的相比,Spark的map函数语义更简单,应用范围更窄。

  Spark的解决方案是首先将每行映射为一组输出值,这组值可能为空值或多值。随后会通过flatMap函数被扁平化。数组中的词会被过滤并被转化为函数中的元组。这个例子中,真正模仿Mapper行为的是flatMap,而不是map。
  groupByKey()
  写一个统计次数的reducer是简单的,在Spark中,reduceByKey可以被用来统计每个单词的总数。比如出于某种原因要求输出文件中每个单词都要显示为大写字母和其数量,在MapReduce中,实现如下:
  public class CountUppercaseReducer extends
  Reducer<Text, IntWritable, Text, IntWritable> {
  @Override
  protected void reduce(Text word, Iterable<IntWritable> counts, Context context)
  throws IOException, InterruptedException {
  int sum = 0;
  for (IntWritable count : counts) {
  sum += count.get();
  }
  context
  .write(new Text(word.toString().toUpperCase()), new IntWritable(sum));
  }
  }

  但是redeceByKey不能单独在Spark中工作,因为他保留了原来的key。为了在Spark中模拟,我们需要一些更像Reducer API的操作。我们知道Reducer的reduce方法接受一个key和一组值,然后完成一组转换。groupByKey和一个连续的map操作能够达到这样的目标:
  groupByKey().map { case (word,ones) => (word.toUpperCase, ones.sum) }
  groupByKey只是将某一个key的所有值收集在一起,并且不提供reduce功能。以此为基础,任何转换都可以作用在key和一系列值上。此处,将key转变为大写字母,将values直接求和。

  setup()和cleanup()

  在MapReduce中,Mapper和Reducer可以声明一个setup方法,在处理输入之前执行,来进行分配数据库连接等昂贵资源,同时可以用cleanup函数可以释放资源。
  public class SetupCleanupMapper extends
  Mapper<LongWritable, Text, Text, IntWritable> {
  private Connection dbConnection;
  @Override
  protected void setup(Context context) {
  dbConnection = ...;
  }
  ...
  @Override
  protected void cleanup(Context context) {
  dbConnection.close();
  }
  }

  Spark中的map和flatMap方法每次只能在一个input上操作,而且没有提供在转换大批值前后执行代码的方法,看起来,似乎可以直接将setup和cleanup代码放在Sparkmap函数调用之前和之后:
  val dbConnection = ...
  lines.map(... dbConnection.createStatement(...) ...)
  dbConnection.close() // Wrong!

  然而这种方法却不可行,原因在于:
  · 它将对象dbConnection放在map函数的闭包中,这需要他是可序列化的(比如,通过java.io.Serializable实现)。而数据库连接这种对象一般不能被序列化。
  · map是一种转换,而不是操作,并且拖延执行。连接对象不能被及时关闭。
  · 即便如此,它也只能关闭driver上的连接,而不是释放被序列化拷贝版本分配的资源连接。

  事实上,map和flatMap都不是Spark中Mapper的最接近的对应函数,Spark中Mapper的最接近的对应函数是十分重要的mapPartitions()方法,这个方法能够不仅完成单值对单值的映射,也能完成一组值对另一组值的映射,很像一个批映射(bulkmap)方法。这意味着mapPartitions()方法能够在开始时从本地分配资源,并在批映射结束时释放资源。

  添加setup方法是简单的,添加cleanup会更困难,这是由于检测转换完成仍然是困难的。例如,这样是能工作的:

  lines.mapPartitions { valueIterator =>
  val dbConnection = ... // OK
  val transformedIterator = valueIterator.map(... dbConnection ...)
  dbConnection.close() // Still wrong! May not have evaluated iterator
  transformedIterator
  }

  一个完整的范式应该看起来类似于:
  lines.mapPartitions { valueIterator =>
  if (valueIterator.isEmpty) {
  Iterator[...]()
  } else {
  val dbConnection = ...
  valueIterator.map { item =>
  val transformedItem = ...
  if (!valueIterator.hasNext) {
  dbConnection.close()
  }
  transformedItem
  }
  }
  }

  虽然后者代码翻译注定不如前者优雅,但它确实能够完成工作。

  flatMapPartitions方法并不存在,然而,可以通过调用mapPartitions,后面跟一个flatMap(a= > a)的调用达到同样效果。

  带有setup和cleanup的Reducer对应只需仿照上述代码使用groupByKey后面跟一个mapPartition函数。

  别急,等一下,还有更多
  MapReduce的开发者会指出,还有更多的还没有被提及的API:
  · MapReduce支持一种特殊类型的Reducer,也称为Combiner,可以从Mapper中减少洗牌(shuffled)数据大小。
  · 它还支持同通过Partitioner实现的自定义分区,和通过分组Comparator实现的自定义分组。
  · Context对象授予Counter API的访问权限以及它的累积统计。
  · Reducer在其生命周期内一直能看到已排序好的key 。
  · MapReduce有自己的Writable序列化方案。
  · Mapper和Reducer可以一次发射多组输出。
  · MapReduce有几十个调优参数。

  有很多方法可以在Spark中实现这些方案,使用类似Accumulator的API,类似groupBy和在不同的这些方法中加入partitioner参数的方法,Java或Kryo序列化,缓存和更多。由于篇幅限制,在这篇文章中就不再累赘介绍了。

  需要指出的是,MapReduce的概念仍然有用。只不过现在有了一个更强大的实现,并利用函数式语言,更好地匹配其功能性。理解Spark RDD API和原来的Mapper和ReducerAPI之间的差异,可以帮助开发者更好地理解所有这些函数的工作原理,以及理解如何利用Spark发挥其优势。

简述Hadoop的MapReduce与Googl的MapReducc 之间的关系:

江湖传说永流传:谷歌技术有"三宝",GFS、MapReduce和大表(BigTable)!

谷歌在03到06年间连续发表了三篇很有影响力的文章,分别是03年SOSP的GFS,04年OSDI的MapReduce,和06年OSDI的BigTable。SOSP和OSDI都是操作系统领域的顶级会议,在计算机学会推荐会议里属于A类。SOSP在单数年举办,而OSDI在双数年举办。

那么这篇博客就来介绍一下MapReduce。

1. MapReduce是干啥的

因为没找到谷歌的示意图,所以我想借用一张Hadoop项目的结构图来说明下MapReduce所处的位置,如下图。


Hadoop实际上就是谷歌三宝的开源实现,Hadoop MapReduce对应Google MapReduce,HBase对应BigTable,HDFS对应GFS。HDFS(或GFS)为上层提供高效的非结构化存储服务,HBase(或BigTable)是提供结构化数据服务的分布式数据库,Hadoop MapReduce(或Google MapReduce)是一种并行计算的编程模型,用于作业调度。

GFS和BigTable已经为我们提供了高性能、高并发的服务,但是并行编程可不是所有程序员都玩得转的活儿,如果我们的应用本身不能并发,那GFS、BigTable也都是没有意义的。MapReduce的伟大之处就在于让不熟悉并行编程的程序员也能充分发挥分布式系统的威力。

简单概括的说,MapReduce是将一个大作业拆分为多个小作业的框架(大作业和小作业应该本质是一样的,只是规模不同),用户需要做的就是决定拆成多少份,以及定义作业本身。

下面用一个贯穿全文的例子来解释MapReduce是如何工作的。

2. 例子:统计词频

如果我想统计下过去10年计算机论文出现最多的几个单词,看看大家都在研究些什么,那我收集好论文后,该怎么办呢?

方法一:我可以写一个小程序,把所有论文按顺序遍历一遍,统计每一个遇到的单词的出现次数,最后就可以知道哪几个单词最热门了。

这种方法在数据集比较小时,是非常有效的,而且实现最简单,用来解决这个问题很合适。

方法二:写一个多线程程序,并发遍历论文。

这个问题理论上是可以高度并发的,因为统计一个文件时不会影响统计另一个文件。当我们的机器是多核或者多处理器,方法二肯定比方法一高效。但是写一个多线程程序要比方法一困难多了,我们必须自己同步共享数据,比如要防止两个线程重复统计文件。

方法三:把作业交给多个计算机去完成。

我们可以使用方法一的程序,部署到N台机器上去,然后把论文集分成N份,一台机器跑一个作业。这个方法跑得足够快,但是部署起来很麻烦,我们要人工把程序copy到别的机器,要人工把论文集分开,最痛苦的是还要把N个运行结果进行整合(当然我们也可以再写一个程序)。

方法四:让MapReduce来帮帮我们吧!

MapReduce本质上就是方法三,但是如何拆分文件集,如何copy程序,如何整合结果这些都是框架定义好的。我们只要定义好这个任务(用户程序),其它都交给MapReduce。

在介绍MapReduce如何工作之前,先讲讲两个核心函数map和reduce以及MapReduce的伪代码。

3. map函数和reduce函数

map函数和reduce函数是交给用户实现的,这两个函数定义了任务本身。

map函数:接受一个键值对(key-value pair),产生一组中间键值对。MapReduce框架会将map函数产生的中间键值对里键相同的值传递给一个reduce函数。

reduce函数:接受一个键,以及相关的一组值,将这组值进行合并产生一组规模更小的值(通常只有一个或零个值)。

统计词频的MapReduce函数的核心代码非常简短,主要就是实现这两个函数。

[plain] view plaincopy

map(String key, String value):  

// key: document name  

// value: document contents  

for each word w in value:  

EmitIntermediate(w, "1");  

reduce(String key, Iterator values):  

// key: a word  

// values: a list of counts  

int result = 0;  

for each v in values:  

result += ParseInt(v);  

Emit(AsString(result));  

在统计词频的例子里,map函数接受的键是文件名,值是文件的内容,map逐个遍历单词,每遇到一个单词w,就产生一个中间键值对<w, "1">,这表示单词w咱又找到了一个;MapReduce将键相同(都是单词w)的键值对传给reduce函数,这样reduce函数接受的键就是单词w,值是一串"1"(最基本的实现是这样,但可以优化),个数等于键为w的键值对的个数,然后将这些“1”累加就得到单词w的出现次数。最后这些单词的出现次数会被写到用户定义的位置,存储在底层的分布式存储系统(GFS或HDFS)。

4. MapReduce是如何工作的


上图是论文里给出的流程图。一切都是从最上方的user program开始的,user program链接了MapReduce库,实现了最基本的Map函数和Reduce函数。图中执行的顺序都用数字标记了。

MapReduce库先把user program的输入文件划分为M份(M为用户定义),每一份通常有16MB到64MB,如图左方所示分成了split0~4;然后使用fork将用户进程拷贝到集群内其它机器上。

user program的副本中有一个称为master,其余称为worker,master是负责调度的,为空闲worker分配作业(Map作业或者Reduce作业),worker的数量也是可以由用户指定的。

被分配了Map作业的worker,开始读取对应分片的输入数据,Map作业数量是由M决定的,和split一一对应;Map作业从输入数据中抽取出键值对,每一个键值对都作为参数传递给map函数,map函数产生的中间键值对被缓存在内存中。

缓存的中间键值对会被定期写入本地磁盘,而且被分为R个区,R的大小是由用户定义的,将来每个区会对应一个Reduce作业;这些中间键值对的位置会被通报给master,master负责将信息转发给Reduce worker。

master通知分配了Reduce作业的worker它负责的分区在什么位置(肯定不止一个地方,每个Map作业产生的中间键值对都可能映射到所有R个不同分区),当Reduce worker把所有它负责的中间键值对都读过来后,先对它们进行排序,使得相同键的键值对聚集在一起。因为不同的键可能会映射到同一个分区也就是同一个Reduce作业(谁让分区少呢),所以排序是必须的。

reduce worker遍历排序后的中间键值对,对于每个唯一的键,都将键与关联的值传递给reduce函数,reduce函数产生的输出会添加到这个分区的输出文件中。

当所有的Map和Reduce作业都完成了,master唤醒正版的user program,MapReduce函数调用返回user program的代码。

所有执行完毕后,MapReduce输出放在了R个分区的输出文件中(分别对应一个Reduce作业)。用户通常并不需要合并这R个文件,而是将其作为输入交给另一个MapReduce程序处理。整个过程中,输入数据是来自底层分布式文件系统(GFS)的,中间数据是放在本地文件系统的,最终输出数据是写入底层分布式文件系统(GFS)的。而且我们要注意Map/Reduce作业和map/reduce函数的区别:Map作业处理一个输入数据的分片,可能需要调用多次map函数来处理每个输入键值对;Reduce作业处理一个分区的中间键值对,期间要对每个不同的键调用一次reduce函数,Reduce作业最终也对应一个输出文件。

我更喜欢把流程分为三个阶段。第一阶段是准备阶段,包括1、2,主角是MapReduce库,完成拆分作业和拷贝用户程序等任务;第二阶段是运行阶段,包括3、4、5、6,主角是用户定义的map和reduce函数,每个小作业都独立运行着;第三阶段是扫尾阶段,这时作业已经完成,作业结果被放在输出文件里,就看用户想怎么处理这些输出了。

5. 词频是怎么统计出来的

结合第四节,我们就可以知道第三节的代码是如何工作的了。假设咱们定义M=5,R=3,并且有6台机器,一台master。


这幅图描述了MapReduce如何处理词频统计。由于map worker数量不够,首先处理了分片1、3、4,并产生中间键值对;当所有中间值都准备好了,Reduce作业就开始读取对应分区,并输出统计结果。

6. 用户的权利

用户最主要的任务是实现map和reduce接口,但还有一些有用的接口是向用户开放的。

an input reader。这个函数会将输入分为M个部分,并且定义了如何从数据中抽取最初的键值对,比如词频的例子中定义文件名和文件内容是键值对。

a partition function。这个函数用于将map函数产生的中间键值对映射到一个分区里去,最简单的实现就是将键求哈希再对R取模。

a compare function。这个函数用于Reduce作业排序,这个函数定义了键的大小关系。

an output writer。负责将结果写入底层分布式文件系统。

a combiner function。实际就是reduce函数,这是用于前面提到的优化的,比如统计词频时,如果每个<w, "1">要读一次,因为reduce和map通常不在一台机器,非常浪费时间,所以可以在map执行的地方先运行一次combiner,这样reduce只需要读一次<w, "n">了。

map和reduce函数就不多说了。

7. MapReduce的实现

目前MapReduce已经有多种实现,除了谷歌自己的实现外,还有著名的hadoop,区别是谷歌是c++,而hadoop是用java。另外斯坦福大学实现了一个在多核/多处理器、共享内存环境内运行的MapReduce,称为Phoenix(介绍),相关的论文发表在07年的HPCA,是当年的最佳论文哦!

使用mapreduce实现第一个数据源里面性别为男和女的各多少人: 时开发的时候会遇到很多需要将HDFS上多个数据源的某个字段做为关联字段,得出多个数据源的笛卡儿积。了解了MapReduce多数据源关联的基本思路后就很简单。
基本思路:在Map输入阶段获取输入路径,在Map输出阶段根据路径的不同加以区分,即在将关联的列作为Key,在Value中加以区分是哪个数据源的数据,接着在Reduce的输入阶段,在reduce方法的入参会得到所有Key相同的集合,这样便可对数据进行响应的组装,这样便可完成2个数据源的关联,多个数据源的关联也类似。
下面附上本人写的

mapreduce程序的容错机制是怎么样的: 一、 首先要知道此前提 转载 若在windows的Eclipse工程中直接启动mapreduc程序,需要先把hadoop集群的配置目录下的xml都拷贝到src目录下,让程序自动读取集群的地址后去进行分布式运行(您也可以自己写java代码去设置job的configuration属性)。 ...

3.下列有关于大数据技术或计算模式及其代表产品有误的是()。 A. MapReduce是针对大规模: B 不是百度公司,是谷歌公司为了解决日志超大的问题

  • 05厚的彩钢板零售多少钱一米

    4本名模系列的小说是什么,有一本是香奈儿名模,其余三本是什么?有没得下载?: 纪梵希名模 GUCCI 名模 圣罗兰名模 ...

    527条评论 3251人喜欢 4712次阅读 365人点赞
  • eve残骸多久消失

    香奈儿亅12sf7883手表系列什: 价格能买辆中级轿车。。您好,chanel陶瓷手表J12系列的dm8820 正品价格大概要20多万元。 如果价格有些偏高的话,您可以选择去香港或者美国的免税区域购买。 ...

    426条评论 5895人喜欢 1469次阅读 292人点赞
  • 云雾茶多少钱

    香奈儿这款山茶花手表多少钱?: 在中国内地只有上海半岛酒店和上海恒隆广场的chanel专卖店有卖,。一共有8个系列。每个系列有N多款且价格都不一样。最便宜的是HKD148,000,最贵的HKD3,680,000。。这些的价格都只是香港半岛和太子广场...

    581条评论 6038人喜欢 3297次阅读 778人点赞
  • 昆区武装部在哪

    吃什么东西可以解决轻度一氧化碳中毒?: 煤气中毒后胃肠道的消化力也变的弱了。在饮食上,应该注意高营养,易消化,清淡一些的食物,粥和去掉油的鸡汤比较好。水果要多吃点。要戒烟戒酒,少吃刺激大,不易消化的食物。想要解决一氧化碳中毒,吃什么都没用,通风最关键,最好...

    347条评论 1882人喜欢 2516次阅读 434人点赞
  • 02的cv是谁

    老王,信客和台阶在人物性格描写上的相同和不同之处: 《阿长与山海经》里面爱是关怀之爱... 《背影》里爱是亲人之爱... 《台阶》爱是亲人之爱... 《老王》爱是.关心友爱..《信客》爱是.奉献之爱 . ...

    413条评论 5624人喜欢 1146次阅读 411人点赞
  • 14医师执业资格成绩多少及格

    老特莱手表在瑞士多少钱: 劳特莱一般在2000-5000+左右,十分专业的机械表品牌。这个牌子一般会有9折,买的时候多谈谈。注意看表盘和后盖的Swiss made。 手表向来是每个男士的追求,一款手表可以体现一个男士的身份以及实力。不管你现在...

    471条评论 4558人喜欢 1878次阅读 282人点赞