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

【问底】许鹏:使用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、机器学习、智能算法等相关大数据观点,大数据技术,大数据平台,大数据实践,大数据产业资讯等服务。

一个自动更换墙纸的小软件-VB资料 VB用 VB 设 计 VCD 播 放 器 VB用API播放 .wav 声音文件 VB用MCI指令进行多媒体编程 用VB5.0编写自己的MP3播放器 用VB6.0编写电脑抽奖程序 用VB6的双通道技术获得影碟片断 用VBScript制作活动主页 用VB编写DirectX7.0游戏(下) 用VB编写FLASH动画播放器 用VB设计VCD播放器 用VB实现队列播放MP3 用VB实现屏幕滚屏保护效果 用VB制作下雪的特技景象 用VB自制屏幕保护程序 用Visual Basic实现多画面播放功能 雨滴式的显示图片 -VB资料 在VB5.0中制作多媒体界面 在VB5中将英文字母及阿拉伯数字旋转任意角度 在VB5中如何使机箱内的小喇叭发出不同的声音? 在VB6.0中播放GIF动画 在VB应用程序中恰当的使用声音 在VB应用软件中实现动画效果 在VB中播放AVI文件 在VB中建立司旋转的文本特效 在VB中如何创建闪烁(标语)屏 在VB中显示动画鼠标图标 在VB中用PictureClip控件实现动画 在Visual Basic 6.0中实现自动播放VCD VB怎样在VB中播放Flash动画。 VB制作TopMost窗口 怎样把金钱变量转换成字符串变量? 有人知道如何在application中取出拨号地址的吗? 这不公平!!!!!!! Delphi 指针问题,请大家帮忙! web assistant怎么根据数据库中的数据生成一个页面?那个页面要我自己的样式? 大家帮我看看错在那里!谢谢! 请问有没有用自己的机子作服务器的? 帮我看看代码 日志钩子的安装问题? 如何使用。MDB文件 由于上一题回帖子的人数众多,导致分数不够,所以再开一帖!继续!关于用vb进行文件的读写问题! 怎样在数据库中输入了许多条记录后, 一次性存盘成功? 改变光驱盘符?很急很急 在Oracle中怎样加已经存在的数据文件? 我想请高手帮忙 !! 请问目前那一本参考书对DELPHI初学者有很大提高? 一个关于udp重发的问题 如何在delphi程序里调用vc写的exe执行文件。 如何将query中的内容输出到文本文件,然后还能将该文本文件再导入进来?急急急!!!!!!!!!!! 急急急!!我的计算机找不到硬盘了45分 如何求任意多边形的重心 紧急求助:请问java有没有比较丰富的多媒体控件?比如录音的控件??? 急急急!!!我的计算机找不到硬盘了,45分 如何把一个字段的内容求和,然后把结果存入另一表! 请教,怎样把一个记录数组用VB读入ACCESS 2000数据库中? 关于货币类型的问题? the script too large ????????我快疯了。 什么地方有Sybase与Oracle的比较资料? 急急急!!!我的计算机找不到硬盘了,40分 问一下大家 复活节彩蛋 win2000 professional下如何配置weblogic6.0 jsp和javasript如何通讯? 急!!!如何把'¥100'字串转化为浮点型100.00 用OleContainer1将一个WORD文档存进数据库后如何将它从数据库中取出??? 关于SNMP的问题(请高手回答,送40分) 谁想过要戒水?戒成了吗?又渴了吗? 我用在各种机器上使用Win2000,从来没有down过, 真是太奇怪了??? 请问如何确定操作系统系统是中文的还是英文的? 向外国用户发注册码时候应该说些什么,才能让别人觉得你比较专业? 如何捕获ADO的异常信息 struct结构的数据存储是用的什么顺序方式呀? 能介绍几本关于BCB的适合初学者阅读的书吗? 高手进来,struct结构的数据存储是用的什么方式呀 高分!高手请进!!! Newton 有关StoredProc的 各位大虾进来看看,Debug时的错误~~~~~~~ First-chance exception 和 User breakpoint ,帮帮我啊!!! 虽然我也回复没有分,但有意思的帖子,但我对分数高的帖子更有热情,我是不是很势利?? 我的服务器是unix 哪位提供最简单的图片存入库中的代码 英语有哪些标点符号 英语翻译我想写一封信给Daniel,不过我的英语不行,请帮我翻译一些句子,请不要发在线翻译的结果给我,1 哈利波特系列是我最喜欢的书之一.读书的时候我的思绪在奇妙的魔法世界游走,但在看 联想笔记本键盘字母变数字? 英文里为什么很少用标点符号?印象中括号,引号,破折号都很少见,书名号更是根本没有,常用的只有逗号句号和问号,偶尔能看到个引号.这是为啥捏?3Q 英语翻译新年期间收到叔叔的一封邮件,内容是:叔叔们准备寄700美元回家乡给我们过新年,但是到目前为止,我们并没有收到关于这700美元的任何信息!在发这封邮件之前,我已经发过两封邮件 下面的字母各代表什么数字?(不同字母代表不同数字.)a 0 b c 3 - x 7 2 y =7 7 7a=?b=?c=?x=?y=? 英语翻译英文句子里电影名字是用《》书名号括上,还是用“”引号括上? 英语翻译Hello,My name is Loyce Agurma,I came acrose your profile hi.baidu.com I felt it and decide to send you a massage,to ask you for friendship .you know having a prophesy of love over someone there most be odds around the,but no matter the od 下面算是中相同的字母代表相同的数字,不同的字母代表不同的数字.每个字母各表示什么数字? 填写标点符号, 如何写英文祝贺信 手机ID号是按哪些数字和字母啊? 标点符号填写1雨的力量在于它可使一望无际的黄土高原转眼变得沟沟壑壑()混乱不堪()而知识的力量则在于它可改变命运()扭转乾坤(),缔造美好的未来.2不要在光线暗的地方看书( 这封信怎么写?英语Contact person是 Julie Murphy,公寓名字是Medical Center Apartments.它有三种,1 bedroom,2 bedroom和3 bedroom,我想选这个3 bedroom,住6个人最划算的这个. Photoshop选颜色画面的下面前面带#号的选项 ,有是全是数字有时全是字母有时是数字字母组合那个选项是做什么的? 填写标点符号 字母找规律1、BEH,ELM,LN( )2、CFL,FKP,KR( )3、KFP( ).DML( ) 4、ELN( ).ADG( ) 沪牌照沪+字母 字母+四位数字的号码和沪+字母 +全数字的有什么差别?现在上海的私车牌照有的是比方:沪D H1234,有的是沪D 12345 这两种牌照有什么差别? 问一个标点符号书写问题如果用格子信纸书写到每一行还有一个空格时,这时正好这句话还差一个字,如果加上句末的标点符号就需要两个空格了.通常遇见这种情况下是不是这最后一个空格就 英语字母找规律A,S,D,F,G,H,J_,_.请问该填什麽?规律是什麽? 数字30~40用英语怎么写?35~40的就可以了~ 名信片的英语怎么写 看字母 找规律ABAABAAABAAAABAAAAABAAAAAAB.按以上的规律,那么前2005有几个B 英语数字1-30 “电邮”用英文怎么写 英语比赛,要写一篇英语作文,布置怎么写英语信. 我想给字母找规律根据提示写字母A D G D I N I P ( ) 这封英文信如何写?由于某个客户的订单量太少,老板决心停止与其的发展.现在要写这样一封信,委婉的表达该意思,我该如何写是好?50分悬赏,好的话再酌情追加. "英文怎么写?你...以上英文怎么写? 找规律填字母.(1)K F P () (2)E I N () A D G ()D M I ()(1)K F P ( ) (2)E I N ( ) D M I ( ) A D G ( ) 谢谢你的回信.以及你对我的家人和公司的关心.我们都很好,希望你也很好.这么长时间没有联系,我感到抱歉,因为近来工作实在是太忙了.很期盼你来到北京观看08年奥运会,相信那一定是一次让 英语信怎么写 During the summer holiday there will be a new schedule.C 1 for meal and l 2 service hours and for bus schedules will appear on the wall outside the dining room.We are making weekly film and concert schedules.They will a 3 each Wednesday outside the l 原文:照片收到.不知你现在可好,奥运会期间有没有来北京?这些照片是我在杭州西湖拍的,西湖,那里很美,是人间天堂.你还会来中国吗?祝愿你一切顺利!吻你漂亮的女儿. 《信我 》的英文怎么写 潮州话数字1-10和26个英文字母怎么读?和普通话发音不同的请注明读音,0,2,5,10怎么读?用汉字表示出来好吗? 求助写封英文信假设你是李华,你的朋友来中国玩,请写信邀请他来你家乡玩,用英文写,活动内容有游泳,跑步,爬山,吃海鲜,交通坐飞机,机场有45路车,到最后一站下,会去接他 我喜欢你 你信么英语 (英语题)根据首字母填空(10题)1.Monica h_____ three books and apencil case.2.Do you h_____ a baseball bat?3.Let's p_____ soccer.4.That's _____ interesting.5.I don't w_____ TV in the evening.6.How do you s_____ pencils?7.There are so 中文意思如下:收到你的信很高兴,我看了你的相册,真羡慕你走了那么多的地方,每个地方都留下了很多故事和回忆吧,真好!真的很希望我也能早点去你走过的地方看看.你在家平时都做些什么 我说我喜欢你,你信不?英文怎么翻译 英语首字母填空 急! 所有空都得填出来(数清了,是10个空)"Be careful" is used very often in China to show care f______ others. But in Britain it sounds like giving an order or w_______. You could say that to younger people but n_____ 谁能帮我写英文信信的大致内容是:我叫XXX 我是那个中国孩子 很高兴能与您相识 并且成为一个临时家庭 我的英文不是太好 我想您已经了解 很抱歉我迟来的问候 请带我向您的家人问好还有 见信速回用英语怎么写 衣服码号有数字的,有英文字母的,到底多大的号对多大的码? 一份写给父母的英文信内容是我在大学中生活个方面的增加了,而且物价也在涨,等原因.希望你的父母能给你增加生活费. 他在信中写了什么吗 用英语怎么说 用户名由6-20位长度的数字,英文字母和标点符号组成,至... 中文标点和英文标点转换有没有快捷键转换中文标点和英文标点?而不用再去输入法图标上点击. 昨晚我写了一封信(求英语翻译) ORACLE SQL 获取26个大写英文字母A-Z形如:字母ABCD……Z不用union的方式 输入的中文标点符号与英文标点符号有什么区别?中文标点符号与英文标点符号主要是什么功用. 英语信怎么写啊 caxa如何将标注中的数字尺寸换成英文字母?我选编辑-文字内容,经常改不了,还是数字而不是字母,为什么? 怎样切换中文标点和英文标点? ( )the( )( )English?翻译:这封信是用英语写的吗? 笔记本键盘上的英文字母为什么会变成数字?有时候玩着玩着这些英文字母J I O L M U 都会变成数字 一些数字34560 就会按出来是#¥%……这样子为什么会这样?打问号还会变成+ 为什么 笔记本上 关于英文里的标点符号今天上课就是讲这个..听不太懂....不是句号实不实心的问题...是想问在句子中分段的用法.. 英语翻译MIKE JASON先生您好:在北京的机械展览会上,有幸认识您十分的高兴.我公司是经营脚轮,履带板翻新等项目.希望能与贵公司合作.下面是我公司的联系方式天津XX脚轮厂地址:天津市河东区 华硕笔记本键盘的字母变数字了,怎么回事我按键盘的u i o j k l m 是数字 4 5 6 1 2 3 0 请问下是怎么回事啊?怎么才恢复得过来呢?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn