说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

【问底】许鹏:使用Spark+Cassandra打造高性能数据分析平台(二)

HTML文档下载 WORD文档下载 PDF文档下载
Spark,强大的迭代计算框架,内存计算上无可匹敌。Cassandra,优异的列式存储NoSQL,在写入上难逢敌手。《问底》Spark+Cassandra高性能数据分析平台打造进入第二部分,本文主要探讨spark-cassandra-connector。

【导读】笔者( 许鹏)看Spark源码的时间不长,记笔记的初衷只是为了不至于日后遗忘。在源码阅读的过程中秉持着一种非常简单的思维模式,就是努力去寻找一条贯穿全局的主线索。在笔者看来,Spark中的线索就是如何让数据的处理在分布式计算环境下是高效,并且可靠的。

在对Spark内部实现有了一定了解之后,当然希望将其应用到实际的工程实践中,这时候会面临许多新的挑战,比如选取哪个作为数据仓库,是HBase、MongoDB还是Cassandra。即便一旦选定之后,在实践过程还会遇到许多意想不到的问题。

要想快速的解决开发及上线过程中遇到的系列问题,还需要具备相当深度的Linux知识,恰巧之前工作中使用Linux的经验在大数据领域中还可以充分使用。

笔者不才,就遇到的一些问题,整理出来与诸君共同分享。下文为本系列文章的第二部分(点击访问本系列文章开篇):

Cassandra高并发数据读取实现剖析

本文就spark-cassandra-connector的一些实现细节进行探讨,主要集中于如何快速将大量的数据从Cassandra中读取到本地内存或磁盘。

数据分区

存储在Cassandra中的数据一般都会比较多,记录数在千万级别或上亿级别是常见的事。如何将这些表中的内容快速加载到本地内存就是一个非常现实的问题。

解决这一挑战的思路从大的方面来说是比较简单的,那就是将整张表中的内容分成不同的区域,然后分区加载,不同的分区可以在不同的线程或进程中加载,利用并行化来减少整体加载时间。

顺着这一思路出发,要问的问题就是Cassandra中的数据如何才能分成不同的区域。

不同于MySQL,在Cassandra中是不存在Sequence Id这样的类型的,也就是说无法简单的使用seqId来指定查询或加载的数据范围。

既然没有SequenceID,在Cassandra中是否就没有办法了呢?答案显然是否定的,如果只是仅仅支持串行读取,Cassandra早就会被扔进垃圾桶了。

数据分区在Cassandra中至少可以通过两种途径实现 ,一是通过token range,另一个是slice range。这里主要讲解利用token range来实现目的。

1. Token Range

Cassandra将要存储的记录存储在不同的区域中,判断某一记录具体存储在哪个区域的依据是partition key的Hash值。 

在Cassandra 1.2之前,组成Cassandra集群的所有节点(Node),都需要手动指定该节点的Hash值范围也就是Token Range。

手工计算Token Range显然是很繁琐,同时也不怎么容易维护,在Cassandra 1.2之后,引进了虚拟节点(vnode)的概念,主要目的是减少不必要的人工指定,同时也将token range的划分变得更为细粒度。比如原先手工指定token range,只能达到10000这样一个精度,而有了vnode之后,默认安装是每一个物理节点上有256个虚拟节点,这样子的话每一个range的范围就是10000/256,这样变的更为精细。

有关token range的信息存储在cassandra的system命名空间(keyspace)下的local和peers两张表中。其中local表示本节点的token range情况,而peers表示集群中其它节点的token range情况。这两张表中的tokens字段就存储有详细的信息。如果集群中只由一台机器组成,那么peers中的就会什么内容都没有。

简单实验,列出本节点的token range:

use system;desc table local;select tokens from local;
2. Thrift接口

Token Range告诉我们Cassandra的记录是分片存储的,也就意味着可以分片读取。现在的问题转换成为如何知道每一个Token Range的起止范围。

Cassandra支持的Thrift接口中describe_ring就是用来获取token range的具体起止范围的。我们常用的nodetool工具使用的就是thrift接口,nodetool 中有一个describering指令使用的就是describe_ring原语。

可以做一个简单的实验,利用nodetool来查看某个keyspace的token range具体情况。

nodetool -hcassandra_server_addr describering keyspacename

注意将cassandra_server和keyspacename换成实际的内容。

Spark-Cassandra-Connector

在第一节中讲解了Cassandra中Token Range信息的存储位置,以及可以使用哪些API来获取token range信息。

接下来就分析spark-cassandra-connector是如何以cassandra为数据源将数据加载进内存的。

以简单的查询语句为例,假设用户要从demo这个keyspace的tableX表中加载所有数据,用CQL来表述就是:

select * from demo.tableX
上述的查询使用spark-cassandra-connector来表述就是:

sc.cassandraTable(“demo”,”tableX”)

尽管上述语句没有触发Spark Job的提交,也就是说并不会将数据直正的从Cassandra的tableX表中加载进来,但spark-cassandra-connector还是需要进行一些数据库的操作。要解决的主要问题就是schema相关。

cassandraTable(“demo”,”tableX”)只是说要从tableX中加载数据,并没有告诉connector有哪些字段,每个字段的类型是什么。这些信息对后面使用诸如get[String](“fieldX”)来说却是非常关键的。

为了获取字段类型信息的元数据,需要读取system.schema_columns表,利用如下语句可以得到schema_columns表结构的详细信息:

desc table system.schema_columns
如果在conf/log4j.properties中将日志级别设置为DEBUG,然后再执行sc.cassandraTable语句就可以看到具体的CQL查询语句是什么。

1. CassandraRDDPartitioner

Spark-cassandra-connector添加了一种新的RDD实现,即CassandraRDD。我们知道对于一个Spark RDD来说,非常关键的就是确定getPartitions和compute函数。

getPartitions函数会调用CassandraRDDPartitioner来获取分区数目:

override def getPartitions: Array[Partition] = {    verify // let's fail fast    val tf = TokenFactory.forCassandraPartitioner(cassandraPartitionerClassName)    val partitions = new CassandraRDDPartitioner(connector, tableDef, splitSize)(tf).partitions(where)    logDebug(s"Created total ${partitions.size} partitions for $keyspaceName.$tableName.")    logTrace("Partitions: \n" + partitions.mkString("\n"))    partitions  }
CassandraRDDPartitioner中的partitions的处理逻辑大致如下:

  1. 首先确定token range,使用describe_ring
  2. 然后根据Cassandra中使用的Partitioner来确定某一个token range中可能的记录条数,这么做的原因就是为进一步控制加载的数据,提高并发度。否则并发度就永远是256了,比如有一个物理节点,其中有256个vnodes,也就是256个token分区。如果每个分区中大致的记录数是20000,而每次加载最大只允许1000的话,整个数据就可以分成256x2=512个分区。
  3. 对describeRing返回的token range进一步拆分的话,需要使用splitter,splitter的构建需要根据keyspace中使用了何种Partitioner来决定,Cassandra中默认的Partitioner是Murmur3Partitioner,Murmur3Hash算法可以让Hash值更为均匀的分布到不同节点。
  4. splitter中会利用到配置项spark.cassandra.input.split.size和spark.cassandra.page.row.size,分别表示一个线程最多读取多少记录,另一个表示每次读取多少行。

partitions的源码详见CasssandraRDDParitioner.scala

compute函数就利用确定的token的起止范围来加载内容,这里在理解的时候需要引起注意的就是flatMap是惰性执行的,也就是说只有在真正需要值的时候才会被执行,延迟触发。

数据真正的加载是发生在fetchTokenRange函数,这时使用到的就是Cassandra Java Driver了,平淡无奇。

2. fetchTokenRange

fetcchTokenRange函数使用Cassandra Java Driver提供的API接口来读取数据,利用Java API读取数据一般遵循以下步骤:

val cluster = ClusterBuilder.addContactPoint(“xx.xx.xx.xx”).buildval session = cluster.connectval stmt = new SimpleStatement(queryCQL)session.execute(session)session.closecluster.close

addContactPoint的参数是cassandra server的ip地址,在后面真正执行cql语句的时候,如果集群有多个节点构成,那么不同的cql就会在不同的节点上执行,自动实现了负载均衡。可以在addContactPoint的参数中设定多个节点的地址,这样可以防止某一节点挂掉,无法获取集群信息的情况发生。

session是线程安全的,在不同的线程使用同一个session是没有问题的,建议针对一个keySpace只使用一个session。

3. RDD中使用Session

在Spark RDD中是无法使用SparkContext的,否则会形成RDD嵌套的现象,因为利用SparkContext很容易构造出RDD,如果在RDD的函数中如map中调用SparkContext创建一个新的RDD,则形成深度嵌套进而导致Spark Job有嵌套。

但在实际的情况下,我们需要根据RDD中的值再去对数据库进行操作,那么有什么办法来打开数据库连接呢?

解决的办法就是直接使用Cassandra Java Driver而不再使用spark-cassandra-connector的高级封装,因为不能像这样子来使用cassandraRDD。

sc.cassandraRDD(“ks”,”tableX”).map(x=>sc.cassandraRDD(“ks”,”tableX”).where(filter))
如果是直接使用Cassandra Java Driver,为了避免每个RDD中的iterator都需要打开一个session,那么可以使用foreachPartition函数来进行操作,减少打开的session数。

val  rdd1 = sc.cassandraTable(“keyspace”,”tableX”)	rdd1.foreachPartition( lst => {		val cluster = ClusterBuilder.addContactPoint(“xx.xx.xx.xx”).build		val session = cluster.connect		while ( iter.hasNext ) {		 	val  elem = iter.next			//do something by using session and elem		}		session.close		cluster.close	})

其实最好的办法是在外面建立一个session,然后在不同的partition中使用同一个session,但这种方法不行的原因是在执行的时候会需要”Task not Serializable”的错误,于是只有在foreachPartition函数内部新建session。

数据备份

尽管Cassandra号称可以做到宕机时间为零,但为了谨慎起见,还是需要对数据进行备份。

Cassandra提供了几种备份的方法

  1. 将数据导出成为json格式
  2. 利用copy将数据导出为csv格式
  3. 直接复制sstable文件

导出成为json或csv格式,当表中的记录非常多的时候,这显然不是一个好的选择。于是就只剩下备份sstable文件了。

问题是将sstable存储到哪里呢?放到HDFS当然没有问题,那有没有可能对放到HDFS上的sstable直接进行读取呢,在没有经过任务修改的情况下,这是不行的。

试想一下,sstable的文件会被拆分为多个块而存储到HDFS中,这样会破坏记录的完整性,HDFS在存储的时候并不知道某一block中包含有完成的记录信息。

为了做到记录信息不会被拆分到多个block中,需要根据sstable的格式自行提取信息,并将其存储到HDFS上。这样存储之后的文件就可以被并行访问。

Cassandra中提供了工具sstablesplit来将大的sstable分割成为小的文件。

DataStax的DSE企业版中提供了和Hadoop及Spark的紧密结合,其一个很大的基础就是先将sstable的内容存储到CFS中,大体的思路与刚才提及的应该差不多。

对sstable存储结构的分析是一个研究的热门,可以参考如下的链接。

  • https://www.fullcontact.com/blog/cassandra-sstables-offline/

之所以要研究备份策略是想将对数据的分析部分与业务部分相分离开,避免由于后台的数据分析导致Cassandra集群响应变得缓慢而致前台业务不可用,即将OLTP和OLAP的数据源分离开。

通过近乎实时的数据备份,后台OLAP就可以使用Spark来对数据进行分析和处理。

高级查询 Cassandra+Solr

与传统的RDBMS相比,Cassandra所能提供的查询功能实在是弱的可以,如果想到实现非常复杂的查询功能的,需要将Cassandra和Solr进行结合。

DSE企业版提供了该功能,如果想手工搭建的话,可以参考下面的链接:

  1. http://www.slideshare.net/planetcassandra/an-introduction-to-distributed-search-with-cassandra-and-solr 
  2. https://github.com/Stratio/stratio-cassandra开源方面的尝试 Cassandra和Lucene的结合

共享SparkContext

SparkContext可以被多个线程使用,这意味着同个Spark Application中的Job可以同时提交到Spark Cluster中,减少了整体的等待时间。

在同一个线程中, Spark只能逐个提交Job,当Job在执行的时候,Driver Application中的提交线程是处于等待状态的。如果Job A没有执行完,Job B就无法提交到集群,就更不要提分配资源真正执行了。

那么如何来减少等待时间呢,比如在读取Cassandra数据的过程中,需要从两个不同的表中读取数据,一种办法就是先读取完成表A与读取表B,总的耗时是两者之和。

如果利用共享SparkContext的技术,在不同的线程中去读取,则耗时只是两者之间的最大值。

在Scala中有多种不同的方式来实现多线程,现仅以Future为例来说明问题:

val ll  = (1 to 3 toList).map(x=>sc.makeRDD(1 to 100000 toList, 3))val futures = ll.map ( x => Future {		x.count()	})val fl = Future.sequencce(futures)Await.result(fl,3600 seconds)

  1. 简要说明一下代码逻辑
  2. 创建三个不同的RDD
  3. 在不同的线程(Future)中通过count函数来提交Job
  4. 使用Await来等待Future执行结束

更多《问底》内容

  • 【问底】严澜:数据挖掘入门(一)——分词
  • 【问底】Yao Yu谈Twitter的百TB级Redis缓存实践
  • 【问底】王帅:深入PHP内核(一)——弱类型变量原理探究 
  • 【问底】王帅:深入PHP内核(二)——SAPI探究
  • 【问底】王帅:深入PHP内核(三)——内核利器哈希表与哈希碰撞攻击
  • 【问底】静行:FastJSON实现详解
  • 【问底】李平:大型网站的灵魂——性能
  • 【问底】许鹏:使用Spark+Cassandra打造高性能数据分析平台(一)
  • 【问底】许鹏:使用Spark+Cassandra打造高性能数据分析平台(二)
  • 【问底】徐汉彬:大规模网站架构的缓存机制和几何分形学
  • 【问底】徐汉彬:亿级Web系统搭建——单机到分布式集群
《问底》是CSDN云计算频道新建栏目,以实践为本,分享个人对于新时代软件架构与研发的深刻见解。在含有“【问底】”字样标题的文章中,你会看到某个国外IT巨头的架构分享,会看到国内资深工程师对某个技术的实践总结,更会看到一系列关于某个新技术的探索。《问底》邀请对技术具有独特/深刻见解的你一起打造一片只属于技术的天空,详情可邮件至zhonghao@csdn.net。

CSDN诚邀您参加中国大数据有奖大调查活动,只需回答23个问题就有机会获得最高价值2700元的大奖(共10个), 速度参与进来吧!

第八届中国大数据技术大会(Big Data Technology Conference 2014,BDTC 2014)将于2014年12月12日-14日在北京新云南皇冠假日酒店召开。传承自2008年,历经七届沉淀,“中国大数据技术大会”是目前国内最具影响、规模最大的大数据领域技术盛会。本届会议,你不仅可以了解到Apache Hadoop提交者Uma Maheswara Rao G(兼项目管理委员会成员)、Yi Liu,以及Apache Hadoop和Tez项目管理委员会成员Bikas Saha等分享的通用大数据开源项目的最新成果和发展趋势,还将斩获来自腾讯、阿里、Cloudera、LinkedIn、网易等机构的数十场干货分享。 门票限时折扣中, 预购从速。


免费订阅“CSDN大数据”微信公众号,实时了解最新的大数据进展!

CSDN大数据,专注大数据资讯、技术和经验的分享和讨论,提供Hadoop、Spark、Impala、Storm、HBase、MongoDB、Solr、机器学习、智能算法等相关大数据观点,大数据技术,大数据平台,大数据实践,大数据产业资讯等服务。

告别丑陋banner条,InMobi联合开发者尝试原生广告 免费游戏开发经验谈:第一印象很重要 《近匠》小旭音乐:游戏音乐金牌匠人的练级之路 日600亿消息,月4.65亿用户——WhatsApp的Erlang世界 一周热点:Cloudera新一轮融资总额已达9亿美元 【走近院士】李未:实现云服务的有效方法是群体软件工程 大神云集 大型创客聚会2014深圳Maker Faire盛大开幕 直击Maker Faire,将精彩“一网打尽”! 电池革命:超级充电器来袭,30秒为手机充满电 风雨13载,Windows XP今起正式退役 向Facebook看齐,Twitter收购Android屏幕待机应用开发商Cover 绝对的超现实!Jaunt打造360&#176;全景VR电影 Unite China 2014课程解析:行业解决方案专场免费开放 Manhattan,Twitter规模的实时、多租户分布式数据库 Ceph浅析(中):结构、工作原理及流程 孙元浩:基于Spark引擎的高速内存分析和挖掘工具应用 腾讯私有云背后的团队,品高要做企业云计算的产品经理 撼动企业应用架构的十大技术趋势 Airbnb的管理之道:产品设计的点评策略与技巧 Windows 8.1 Update 1的下载地址和八点须知 《近匠》棱镜:手游渠道SDK平台的技术历程 OpenSSL究竟为何物,为何它的影响力如此之大? Redis大冒险:如何跳出SQL这个坑 【走近院士】张尧学:基于透明计算的云操作系统 微软转型之路:从Build 2014开始 大势所趋 HTML5成Web开发者最关心的技术 从火种到核心,浅析Hadoop大数据用户的演变 搭建高可用的MongoDB集群(上):MongoDB的配置与副本集 软硬件协同创新,共建未来数据中心 优秀Unix管理员的七个习惯 2014Unity亚洲开发者大会倒计时 干货内容日程汇总 系统分析员VS博士 C#连接Oracle? 关于<BASE> 那里有WebDB下载啊. 在ListCtrl里加类似Combo Box的东西,能实现吗? windows2000下vb的一个小问题~~ 如何把当前路径加入查找路径中?立即给分! 对选用不同的纸张大小,在预览中能看出效果吗? 请问怎么在PB6.0中实现Foxpro(*.dbf)的数据导入,到ASA库中 j2me里怎么才能实现图象的滤镜效果?waiting... CDbSet m_dbSet(NULL)在哪一步才能得到一个CDatabase对象的错针? 新手提问:“镜象”是什么意思 求教,如何配置使性能达到最佳,详情见文 怎样在广域网中提高传屏响应速度?帮帮忙!急啊. 在文件钩子当中如何判断是打开文件操作,还是创建文件操作 怎样在applet程序中显示一幅jpeg图片?该图片存在于c:\image\下。 去年12月是谁发的帖子“做项目经理难么” 关于图层拖拽的问题 我有一块硬盘,迈托4.3G,开格式化分时说错误设备或0磁道损坏,后来fdisk分区,启动无效 这是个什么错误啊~ 第一次做控件不明白 给点指点啊 急求:从硬盘安装windowsxp时电脑出显不能安装,找不到eula!如何解决? 不用的控件怎样从工程中删除? 怎样将一个表中的全部数据追加到别一个表的后面????在线 我做软件这些年 求scjd的模拟题 为什么我连续给一个socket send三次,socket一次就接收完了? 关于HTML代码不区分大小写? 大家看一下这个CListCtrl是啥回事?? Turbo c++3.0怎么使用? 《水园MSN俱乐部宗旨》 ODBC连接数据库的一个问题求教 如何让网页一打开就是全屏模式? 关于打印的问题 怎么彻底卸载linux啊!放分100 如何移动无模式窗体? 一个网络版软件的共享使用问题 在线等待!!! 一个网络版软件的共享使用问题 98怎么与xp不能连网玩游戏?高分送!! 有个问题请大虾帮帮忙! 我该怎么办呀??? ★怎样让窗口的resize在某一指定的范围内? 笔记本问题~ TURBO C 中显示鼠标和图形方式的问题(看我的源代码) ACCESS中的SQL语句不支持limit语法吗?~~急问啊~~~ 为什么会这样? 我在网上下了个C1TrueDBGrid 不知怎么用?有没有什么限制?请各位帮忙? 只有这里可以发发牢骚了,斑竹别删 100分(不够可以再加!)求《PC游戏编程--人机博弈》光盘源代码!!在线等 网上考试系统热卖中............(请版主勿删) 100分解决文件流问题 做紫外光谱时吸收峰一般在什么范围 piece和bar的区别 填人体器官词 ( )枪( )剑 食物油易溶于哪种物质 bar用于长方形物体那piece呢? 填与人体器官有关的词:归()似箭、()()俱裂、()亡()寒、()蜜()剑、狼()狗() 氨气是否极易溶于油 苏丹国家的气候情况 偶然误差可以通过以下哪种方法得以减小? 硝酸铵能否极易溶于油? 请问苏丹的气候条件真的很恶劣吗?国人能适应吗? 不参与淀粉的消化,但参与蛋白质消化的消化液是?A.肠液 B.胰液 C.胃液 D.唾液 摩尔庄园求死党~求家族~我米米号658743 苏丹是哪个半球,什么人种,什么语言,什么宗教,什么气候类型? 人体脑部生长最快的年龄段是 . 摩尔庄园 替我玩、、、 十万分之一天平,该选哪个好呢? 为什么硫酸铜溶液不能放在金属容器中? 摩尔庄园的问题我是09年的老玩家,在一直没玩过,今天登陆后发现什么都变了,现在清玩家们指示一下我该做些什么,真的很怀念,想重新玩,还有需要开超级拉姆吗?今天回家看见09年的脚印想哭 精确到0.1mg的天平到底应该使用什么样的天平?不知道用万分之一的还是十万分之一的?原理是什么?如果是十万分之一,最低和最高称量多少克呢? 徐志摩的《偶然》表达了怎样的爱情观?与舒婷的《致橡树》对比有何不同?或直接把《偶然》的爱情观告诉我就行了 酒精和氯有什么反应 用一道题及解答来介绍什么是模糊数学 CuSO4加什么生成Cu 茶液和酒精混合在一起有什么反应? 一些较浅的伤口破了之后,不流血,流一些透明的液体,基本上不粘,怎么了?有两个月了吧,混身上下都是 cuso4不能与下面哪种容器盛放 是否有氢氧化硫 氢氧化氮 一说? 伤口处的透明液体是什么我的小拇指根手背处蹭破了皮,在蹭伤中应该算是深的了,血没流很多(没到可以滴的程度),但却有白色透明的液体在伤口上(不要忽悠我是血浆,水,我生物成绩很好 某酯C7H14O2经水解得到A和B,A能发生银镜反应,则该酯是 洛伦兹曲线与基尼系数是如何体现收入分配的平等程度的 梅特勒-托利多AG135分析天平价格多少? 我想问一下为什么电磁炉会爆炸?这几天看到几则电磁炉爆炸的新闻,我感觉到很困惑,根据电磁炉发热的原理,电磁炉为什么会爆炸呢?是什么部件爆炸呢?这里有两个链接 收入分配的平等可以用哪些标准衡量( ) A.劳动分配率 B.洛伦斯曲线和基尼系数 C.工资的差异率 D.以上都 现在要用高效液相色谱法测定水样中残留的抗生素 要有水样前处理 实验要有水样前处理 实验 和要做出什么数据和图表 要宋江的性格特征 主要的五件事 要按时间顺序 有一两句话概括 老师留的作业 求教洛伦兹曲线与基尼系数的区别和联系,详细一点的. 什么是参考企业比较法? 电网系统SF6气体有哪些化学性质? 为什么冬天和夏天的温差那么大,又为什么冬天的太阳不是很热,而夏天的太阳热的受不了.种种的这些是由什么造成的,要有科学而缜密的解释. 微观经济学中,基尼系数如何衡量收入分配的状况 梅特勒电子天平十万分之一什么是一分钟后读数吗在高原海拔4000左右,温度一般十几度湿度冬天的话也20以下.用着感觉很不稳定,一开始我们是把要称的样品放在上面等小圆圈消失后等一分钟 为什么饱和烷烃的偶极矩为0 请问肯尼亚的气候怎么样?南苏丹呢? 谁有Waters2487高效液相色谱仪说明书? 唾液淀粉酶在经过高温后还有效吗?比如说将唾液放在90°的高温下加热,然后让它冷了以后还能有用吗,还能再消化淀粉吗? 《美研究显示:现有技术无法克隆人》 阅读题 数学中的作商与1比较法具体是怎样的 地沟油加工成化工原料和柴油?是真是假啊 ··我朋友让我帮他收购类 ··谁愿意合作`? 生殖性克隆不安全,应该禁止与美研究显示:现有技术无法克隆人之间是什么关系 生殖 【讨论】十万分之一或百万分之一的分析天平哪个牌子的好? 下列事物不是利用紫外线辐射的是夏天外出戴太阳镜 将衣服、被褥等放到太阳光下暴晒紫外线诱蝇灯诱杀害虫 验钞机识别伪钞 水中氧元素的化合价+2用化学式表示 地沟油是不是废品啊 还有什么利用价值么 300万吨的地沟油可以制作多少柴油 美的电压力锅水槽里没水,真气水在锅口流不了? 十万分之一的电子天平都有哪些品牌 有关紫外光谱吸收峰强度的问题我做了紫外光谱的光谱扫描 发现有个样品的吸收峰Abs达到了1.4 想问一下这个光谱是否符合要求? 一般做光谱扫描的时候是不是要控制Abs小于1? 如果大于1会有 电离方程式是O++OH-=H2O的化学方程式→_→怎么可能没有 你认真点儿……不会的话就别来误导我…… 伤口白色,还有液体,是不是感染了手术后10天我自己查看伤口,缝针露出的内肉(就是本来在皮肤下的)是白色的,但在伤口结合处已经长出新肉,有很少量的渗出黄色液体,压上去有些微疼,在伤口 土耳其否决“采购中国红旗导弹”的早前新媒:记者陈永洲被批准逮捕 舆情急转日媒:“西进战略”对中国崛起产生重大混装的货车收费站附近爆炸 幸未造成人货车上高速大灯出故障 司机打着手电开借给朋友的豪车撞车后烧成空壳 司机居一脚油门跨过四级台阶 轿车冲进武林路女司机高速追尾车毁人伤 罪魁就是脚上美媒:美国“重返亚洲”战略让中国从中英媒:长期天然气短缺加剧中国空气污染日本解密文件称美曾让其修宪员工工资企业不能再一口价 杭州拟正式义乌集装箱数10年增70多倍 义乌成杭州市公述民评进入第三场 市民拷问地杭州孩儿巷取消52个泊位后道路通行明杭州凤起东路将继续往东延伸 唐家村桥浙江省首次公开省级部门决算及“三公”杭州规定企业拒绝工资集体协商将最高被韩媒:朝鲜军工厂和军列连发火灾 或系党校专家:三中全会部署政治体制改革国研中心:设自贸区不需时间表 成熟一前沿故事28部分客渡船将停航一群“小牛”顶翻湘涛国足再捧一次东亚杯,有木有?大风天,我们如何确保安全赔率显示国足有希望今起3天,7级北风暴雨雷电来了一群“小牛”顶翻湘涛QQ群中一张照片带孩子回家一张错币价值百万元?中国秘密战13患癌婆婆摆地摊卖衣服筹药费青运会武汉足球队誓师朝鲜姑娘夺冠不靠目标靠精神驾校教练车眨眼间“失足”宁泽涛人气不减国足再捧一次东亚杯,有木有?“黑尾巴车”上路一月罚款过万朝鲜姑娘夺冠不靠目标靠精神放量才是进场信号电蚊香闻起来香有毒吗?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘