小米大模型数据开发工程师-武汉
我对于这个岗位的理解
结合这个职位的描述与网上的搜索,对于这个职位我的理解大概是这样的:
- 数据处理:需要使用各种工具(如SQL、Python、Hadoop等)来收集、清洗和处理数据。这可能包括从数据库或其他数据源中提取数据,清洗和整理数据以消除错误和不一致性,以及转换数据以便进行进一步的分析和建模。
- 数据挖掘:在数据处理之后,你需要使用各种数据挖掘算法(如聚类、分类、关联规则等)来从数据中提取有价值的信息。这可能需要熟悉并能够使用各种数据挖掘工具和库(如scikit-learn、TensorFlow等)。
- 数据分析:需要对挖掘出的数据进行分析,以得出有价值的洞察和结论。这可能需要使用各种数据分析工具(如R、Python的pandas库等),并且需要你具备一定的统计知识。
- 数据治理:需要确保数据的质量和一致性,这可能包括数据的清洗、验证、脱敏等工作。此外,还需要建立和维护数据字典,以确保数据的标准化和一致性。
- 开发相关服务:可能需要开发一些服务来支持上述工作,例如自动化数据清洗和处理的工具,数据可视化的工具等。这可能需要熟悉并能够使用各种开发工具和语言(如Java、Python等)。
大模型和大数据的行业前景理解
大模型-理解
首先是对于大模型的理解,最经典的就是chatgpt,PI AI,claude2, Bard,这些是市面上使用体验最好的大语言模型,这也是我平日生活中工作学习必不可少的部分,从它诞生开始我就一直持续的使用,不论是官网的还是二次创作的插件。
从使用体验上看,PI AI是主要面向情感方面的,是一个不错的练习英语口语的工具,情感方面的话,趋近于真人。
然后是逻辑相关的大模型chatgpt和claude-2,Bard他们的逻辑能力差不多,对于各种细小的知识的解答效果很不错,比如我之前面试c++岗位,那个面试官提出来的各种c++底层的问题,写常见的算法,gpt都可以做出很好的回答,但是他的缺点也很明显,那就是他的架构能力,业务逻辑能力,我是做Java开发的时候,经常需要处理一些较为复杂的业务逻辑,这个时候gpt就很难弄清楚了,不如自己编写,然后就是一些特殊的算法,想要让gpt写出来,需要几乎自己把这个算法的几乎没有细节都说的很明白,算法思路很清晰,然后提交给gpt他才可以写对,适合只知道思路但是不会编程或者懒得自己编程的人,其实从这几点也可以看出来gpt是一个特别好的员工,就类似于前几次工业革命一样,机器会淘汰只会那些只会考验体力的人的工作,比如我们常说的Java里面的CRUD。
所以在使用了GPT之后,我对于自己的定位技术的方向的话,如果不从事科研相关的那么就是架构师(不直接参与代码编写,写业务的架构,让gpt或者其他人完善细节,架构师需要很庞大的知识体系,这个与我的知识博主身份很契合),如果从事科研相关的那就是大数据算法工程师类似于这个岗位一样,主要研究各种算法和大模型,这两个职位也是我研究发现以后程序员的两个方向,一个是不断往上走,专注于业务逻辑架构思想,一个是不断的往下走,专注于各种算法科研相关的。
大数据-理解
对于一个学Java的,走大数据开发还是走Java后端开发一直是一个比较争论的点。他的技术栈是有部分重合的。就我自己学习和我们老师教学来看,我的理解是后端开发包含大数据开发,但是大数据开发不包含后端开发,也就是干后端开发的往往也可以干大数据开发,但是干大数据开发的很难转到后端开发,我们教学也是这样的,都显示教完Java的后端开发,然后在科普Java的大数据开发,Java后端开发学到后面,需要处理海量数据的时候自然需要更多的大数据的知识。
- 技术栈:Java后端开发主要涉及到的技术栈包括Java语言本身、数据库(如MySQL)、框架(如Spring、Hibernate等)、服务器(如Tomcat、Jetty等)、缓存(如Redis、Memcached等)、消息队列(如RabbitMQ、Kafka等)等。而大数据开发则需要掌握Hadoop、Spark、Flink、Hive、HBase、Kafka等大数据处理框架,以及Scala、Python等编程语言。
- 工作内容:Java后端开发主要负责实现业务逻辑,包括数据的增删改查、接口的开发和维护、系统的部署和监控等。而大数据开发则主要负责数据的收集、清洗、存储、处理、分析和展示,需要处理的数据量通常在TB级别以上。
- 数据处理能力:Java后端开发主要处理的是结构化数据,数据量相对较小,通常在GB级别以下。而大数据开发则需要处理的数据既包括结构化数据,也包括半结构化数据和非结构化数据,数据量通常在TB级别以上,对数据处理的能力要求更高。
- 学习难度:Java后端开发的学习难度相对较小,只需要掌握Java语言和相关的开发工具和框架即可。而大数据开发的学习难度则相对较大,除了需要掌握Java语言和相关的开发工具和框架,还需要掌握大数据处理框架和相关的数据处理技术,对计算机系统、数据结构和算法等基础知识的要求也更高。
- 转型难度:从Java后端开发转型到大数据开发相对较容易,因为大数据开发的技术栈中有很大一部分是Java后端开发的技术栈,只需要额外学习一些大数据处理框架和相关的数据处理技术即可。而从大数据开发转型到Java后端开发则相对较难,因为Java后端开发涉及到的业务逻辑和系统设计等方面的知识,大数据开发中并不涵盖。
具体技术的理解
Java\python\scala
首先Scala和Java。Java,对于处理大数据非常有效,但是它的面向对象特性并不完全。因此,Scala语言应运而生。Scala是基于Java的语言,它提供了更高级的编程特性和更完善的面向对象特性,有人甚至将其称为"Java++"。Scala与Java的关系,就像C语言与C++的关系一样。Scala在处理大数据,尤其是在使用Apache Spark框架时,更加高效和强大。
然后Python在数据科学领域中的应用已经成为共识。Python语言简洁易读,拥有开放的生态系统,包括大量的数据处理和科学计算库,如NumPy,Pandas和Scikit-learn等。因此,Python常被用于数据分析和大模型的构建,它的灵活性和易用性使得数据科学家和工程师能够更快速地进行原型设计和实现复杂的数据分析任务。
kafka\spark\ETL\maven\gradle
我们可以将大模型数据开发想象成是一家大型的制造厂,而这些技术工具就是厂房中的各种设备。
- Kafka:Kafka就像是厂房的传送带,它负责将原始材料(数据)从一个地方传送到另一个地方。在大数据处理中,Kafka可以实时地处理和传输大量的数据。
- Spark:Spark就像是厂房的加工设备,它能够快速处理和分析传送带上的原始材料(数据)。Spark的强大计算能力使其在处理大数据时效率极高。
- ETL:ETL(提取、转换、加载)就像是厂房的预处理设备,它将原始材料(数据)进行清洗和格式化,使其能够被后续的设备(如Spark)更好地加工。
- Maven/Gradle:Maven和Gradle就像是厂房的管理系统,它们能够确保设备(代码)的正常运行,管理设备的版本和依赖,使得整个生产线(代码库)能够顺利运行。
mongo\mysql\hbase
继续使用我们的制造厂比喻,我们可以将MongoDB、MySQL、HBase等数据仓储工具想象成是厂房的仓库。
- MongoDB:它就像是一个灵活的大仓库,可以存储各种各样的货物(数据)。MongoDB是一个NoSQL数据库,它可以存储非结构化的数据,使得我们可以在其中存储各种形式的数据。
- MySQL:它就像是一个有着严格分类的仓库,每种货物(数据)都有固定的存放位置。MySQL是一个关系型数据库,它按照预定义的模式存储数据,使得我们可以更好地组织和查询数据。
- HBase:它就像是一个巨大的仓库,可以存储大量的货物(数据)。HBase是一个分布式的、面向列的数据库,它可以存储海量的数据,并且可以进行快速的随机读写。
多线程/进程编程/有独立软件架构能力
多线程/进程编程
多线程/进程编程:这就像是制造厂中的自动化生产线,其中每个线程或进程就像是一个单独的工人。在一个单线程/进程的工厂中,工人们必须按顺序完成任务,一个任务完成后,下一个任务才能开始。但在多线程/进程的工厂中,多个工人可以同时进行工作,大大提高了生产效率。在计算机编程中,多线程/进程编程允许程序同时执行多个任务,从而提高程序的效率和响应速度。
- 多线程/进程编程在Java中的应用:
- Java提供了内置的多线程支持,通过使用Thread类或实现Runnable接口来创建和管理线程。
- 使用多线程可以将任务分配给不同的线程并同时执行,提高程序的并发性和响应性。
- Java提供了一些同步机制(如synchronized关键字和Lock接口),用于处理多个线程之间的共享资源访问问题,避免数据竞争和并发错误。
- Java还提供了线程池(ThreadPoolExecutor类)来管理和复用线程,提高线程的利用率和性能。
下面是一个经典的生产者消费者问题的Java多线程示例:展示生产者消费者问题中的经典多线程编程模式,其中生产者和消费者通过共享的缓冲区进行通信和同步。
import java.util.LinkedList; public class ProducerConsumer { public static void main(String[] args) { // 创建共享的缓冲区 LinkedList<Integer> buffer = new LinkedList<>(); // 缓冲区的最大容量 int maxSize = 5; // 创建生产者线程,并传入缓冲区和最大容量 Thread producerThread = new Thread(new Producer(buffer, maxSize)); // 创建消费者线程,并传入缓冲区 Thread consumerThread = new Thread(new Consumer(buffer)); // 启动生产者和消费者线程 producerThread.start(); consumerThread.start(); } } /** * 生产者类,实现了Runnable接口 */ class Producer implements Runnable { private LinkedList<Integer> buffer; // 缓冲区 private int maxSize; // 缓冲区的最大容量 /** * 构造函数,初始化缓冲区和最大容量 * @param buffer 缓冲区 * @param maxSize 最大容量 */ public Producer(LinkedList<Integer> buffer, int maxSize) { this.buffer = buffer; this.maxSize = maxSize; } /** * 线程运行的主要逻辑 */ @Override public void run() { int value = 0; while (true) { synchronized (buffer) { // 如果缓冲区已满,则等待 while (buffer.size() == maxSize) { try { buffer.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 向缓冲区添加元素 buffer.add(value); System.out.println("Produced: " + value); value++; // 通知其他线程可以继续执行 buffer.notify(); } } } } /** * 消费者类,实现了Runnable接口 */ class Consumer implements Runnable { private LinkedList<Integer> buffer; // 缓冲区 /** * 构造函数,初始化缓冲区 * @param buffer 缓冲区 */ public Consumer(LinkedList<Integer> buffer) { this.buffer = buffer; } /** * 线程运行的主要逻辑 */ @Override public void run() { while (true) { synchronized (buffer) { // 如果缓冲区为空,则等待 while (buffer.isEmpty()) { try { buffer.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 从缓冲区取出元素 int value = buffer.removeFirst(); System.out.println("Consumed: " + value); // 通知其他线程可以继续执行 buffer.notify(); } } } }
在这个示例中,我们创建了一个共享的缓冲区(LinkedList)作为生产者和消费者之间的通信通道。生产者线程不断向缓冲区中添加元素,而消费者线程不断从缓冲区中取出元素。
生产者线程在缓冲区已满时等待,消费者线程在缓冲区为空时等待。通过使用synchronized关键字对缓冲区进行加锁,并使用wait()和notify()方法进行线程间的通信,确保生产者和消费者的正确执行顺序和互斥访问。
2.多线程/进程编程在Python中的应用:
- Python的标准库提供了threading模块,用于创建和管理线程。
- 类似于Java,Python也可以通过继承Thread类或实现Runnable接口来创建线程。
- Python的线程模块提供了一些同步原语(如Lock、Semaphore、Condition等),用于处理线程间的同步和互斥操作。
- Python中的多线程编程受到全局解释器锁(GIL)的限制,即同一时间只能有一个线程执行Python字节码,这导致Python的多线程在CPU密集型任务上效果不佳,但在IO密集型任务上仍然可以发挥作用。
生产者-消费者问题是一个经典的并发编程问题,可以使用Python中的多线程和队列来实现。
import threading import time import queue # 创建一个队列作为共享资源 queue = queue.Queue(5) # 生产者线程 class ProducerThread(threading.Thread): def run(self): while True: # 模拟生产过程 time.sleep(1) item = "item" print("生产者生产了一个物品:" + item) queue.put(item) # 消费者线程 class ConsumerThread(threading.Thread): def run(self): while True: # 模拟消费过程 time.sleep(2) item = queue.get() print("消费者消费了一个物品:" + item) # 创建生产者和消费者线程 producer = ProducerThread() consumer = ConsumerThread() # 启动线程 producer.start() consumer.start()
在上面的示例中,我们首先创建了一个队列queue作为共享资源,它的大小被限制为5个物品。
然后,我们定义了一个生产者线程ProducerThread,它的run方法模拟了生产过程。每隔1秒钟生产一个物品,并将其放入队列中。
接下来,我们定义了一个消费者线程ConsumerThread,它的run方法模拟了消费过程。每隔2秒钟从队列中取出一个物品进行消费。
最后,我们创建了一个生产者线程实例producer和一个消费者线程实例consumer,然后分别调用start方法启动线程。
通过使用队列作为共享资源,生产者线程和消费者线程可以安全地进行并发操作,避免了竞态条件和线程间的竞争。
需要注意的是,上述代码中的生产者和消费者线程是无限循环的,可以根据实际需求添加退出条件。
- 多线程/进程编程在Scala中的应用:
- Scala是一种运行在Java虚拟机上的编程语言,它融合了面向对象编程和函数式编程的特性。
- Scala提供了内置的多线程支持,通过使用scala.concurrent包中的Future和Promise等类来创建和管理线程。
- Scala还提供了一些高级的并发原语,如Actor模型和并发集合,用于处理并发和并行编程问题。
- Scala中的多线程编程受到JVM的限制,与Java类似。
在Scala中,可以使用scala.concurrent包中的BlockingQueue来实现生产者-消费者问题。
import scala.concurrent._ import ExecutionContext.Implicits.global import scala.concurrent.blocking import scala.concurrent.Future import scala.util.Random // 创建一个BlockingQueue作为共享资源 val queue = new java.util.concurrent.ArrayBlockingQueue[String](5) // 生产者方法 def producer(): Unit = { while (true) { blocking { val item = "item" println(s"生产者生产了一个物品: $item") queue.put(item) } Thread.sleep(1000) } } // 消费者方法 def consumer(): Unit = { while (true) { blocking { val item = queue.take() println(s"消费者消费了一个物品: $item") } Thread.sleep(2000) } } // 创建生产者和消费者Future val producerFuture = Future { producer() } val consumerFuture = Future { consumer() } // 等待生产者和消费者执行完毕 Await.result(Future.sequence(Seq(producerFuture, consumerFuture)), Duration.Inf)
我们创建了一个BlockingQueue作为共享资源,其大小被限制为5个物品。
接下来,我们定义了producer方法和consumer方法,分别模拟生产者和消费者的行为。在方法中,我们使用blocking函数将代码块包装起来,以确保在执行期间不会阻塞其他线程。
然后,我们使用Future来创建生产者和消费者的并发任务。通过将producer方法和consumer方法传递给Future,它们将在后台线程中执行。
最后,我们使用Await.result等待生产者和消费者的执行完毕,以保证主线程不会提前退出。
需要注意的是,上述代码中的生产者和消费者是无限循环的,可以根据实际需求添加退出条件。
独立软件架构
在后端开发中,以下是一些常见的独立软件架构:
- 分层架构:也被称为n-tier架构,通常将应用程序分为三层:数据访问层,业务逻辑层和表示层。这种架构有助于分离关注点,使得代码更易于理解和维护。
- 微服务架构:这种架构将应用程序分解为一组小型、独立的服务,每个服务都在其自己的进程中运行,并通过轻量级机制(通常是HTTP资源API)进行通信。每个服务都围绕特定的业务功能构建,并可以独立地进行开发和部署。
- 服务导向架构:服务导向架构(SOA)是一种设计模式,其中应用程序由多个独立的服务组成,这些服务通过定义良好的接口和协议进行通信。SOA有助于提高应用程序的可伸缩性和灵活性,因为服务可以独立地进行扩展和修改。
- 事件驱动架构:在事件驱动架构中,状态变化会产生事件,这些事件会触发其他的处理过程。这种架构有助于创建高度可扩展的应用程序,并允许异步处理。
- 领域驱动设计:领域驱动设计(DDD)是一种软件开发方法,它关注的是核心的领域逻辑,并使用丰富的领域模型进行设计。这种架构有助于处理复杂的业务逻辑,并提高软件的可维护性。
- CQRS架构:命令查询责任分离(CQRS)是一种架构模式,它将读操作和写操作分离为两个独立的接口,从而提高了系统的可扩展性和性能。
- RESTful架构:RESTful架构是一种用于设计网络应用的架构风格。它强调资源的概念,并通过使用HTTP协议的标准方法(如GET、POST、PUT、DELETE)进行操作。
软件工程学什么
在学校学习,简单的说就是408和数据库,Javaee,软件工程导论,软件测试,linux,前端开发。
主要还是自学,我担任我们班就业指导面试的面试官,然后负责问他们想要面试什么技术岗位,前端,测试,后端开发(c++,Java,python),项目经理,CTO等等都面试过。