JRQZ

  • en

自用笔记

2024-09-14

Linux服务器配置ES+Kibana

踩坑记录 依旧是参考官网教程:https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html 准备 云服务器配置: 8核;16G;系统盘:100G;数据盘:500G TencentOS Server ES,Kibana分别部署在docker上 安装 安装docker,略 配置环境变量: export ELASTIC_PASSWORD="<ES_PASSWORD>" # password for "elastic" username export KIBANA_PASSWORD="<KIB_PASSWORD>" # Used _internally_ by Kibana, must be at least 6 characters long 安装es docker network create elastic-net docker run -p 0.0.0.0:9200:9200 -d --name elasticsearch --network elastic-net \ -e ELASTIC_PASSWORD=$ELASTIC_PASSWORD \ -e "discovery.type=single-node" \ -e "xpack.security.http.ssl.enabled=false" \ -e "xpack.license.self_generated.type=trial" \ docker.elastic.co/elasticsearch/elasticsearch:8.14.2 安装Kibana # configure the Kibana password in the ES container curl -u elastic:$ELASTIC_PASSWORD \ -X POST \ http://localhost:9200/_security/user/kibana_system/_password \ -d '{"password":"'"$KIBANA_PASSWORD"'"}' \ -H 'Content-Type: application/json' docker run -p 0.
继续阅读
2024-09-14

Linux服务器配置单节点Hadoop

云服务器搭建配置单节点Hadoop踩坑记录 Hadoop官方指南:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/SingleCluster.html 准备 根据团队情况申请云服务器,本文的配置为: 8核;16G;系统盘:100G;数据盘:500G TencentOS Server 方便起见,这里没有使用容器,直接将服务部署在机器上原生运行(后续实际生产应该会转移到docker上) Hadoop安装 安装Java,ssh 机器自带,略 官方推荐安装pdsh yum install pdsh 下载镜像 目前最新版:https://dlcdn.apache.org/hadoop/common/current/hadoop-3.4.0.tar.gz 在主机下载完毕,使用scp命令将镜像上传到服务器: scp -P 36000 hadoop-3.4.0.tar.gz <user>@xxx.xxx.xxx.xxx:/data/download 服务器上解压缩 tar -zxvf hadoop-3.4.0.tar.gz 进入hadoop目录,由于没有配置系统路径,后续操作默认在该目录下进行 配置Java 找到Java安装位置 java -XshowSettings:properties -version 2>&1 | grep 'java.home' 编辑etc/hadoop/hadoop-env.sh # set to the root of your Java installation export JAVA_HOME=/usr/java/latest 运行 bin/hadoop 此时会出现使用文档 HDFS测试 Hadoop集群可设置成如下模式: Local (Standalone) Mode (单节点单进程) Pseudo-Distributed Mode (伪分布式,单节点多进程) Fully-Distributed Mode (全分布式,多节点多进程) 由于只有一个机器,对前两种模式进行测试 Standalone Operation mkdir input cp etc/hadoop/*.
继续阅读
2024-04-24

经典并发编程问题之哲学家进餐

施工中… 原题:https://leetcode.cn/problems/the-dining-philosophers/description/ 题解参考:https://leetcode.cn/problems/the-dining-philosophers/solutions/2130703/li-shun-xian-cheng-zheng-qiang-xin-hao-l-gzb1/ 5 个沉默寡言的哲学家围坐在圆桌前,每人面前一盘意面。叉子放在哲学家之间的桌面上。(5 个哲学家,5 根叉子) 所有的哲学家都只会在思考和进餐两种行为间交替。哲学家只有同时拿到左边和右边的叉子才能吃到面,而同一根叉子在同一时间只能被一个哲学家使用。每个哲学家吃完面后都需要把叉子放回桌面以供其他哲学家吃面。只要条件允许,哲学家可以拿起左边或者右边的叉子,但在没有同时拿到左右叉子时不能进食。 假设面的数量没有限制,哲学家也能随便吃,不需要考虑吃不吃得下。 设计一个进餐规则(并行算法)使得每个哲学家都不会挨饿;也就是说,在没有人知道别人什么时候想吃东西或思考的情况下,每个哲学家都可以在吃饭和思考之间一直交替下去。 哲学家从 0 到 4 按 顺时针 编号。请实现函数 void wantsToEat(philosopher, pickLeftFork, pickRightFork, eat, putLeftFork, putRightFork): philosopher 哲学家的编号。 pickLeftFork 和 pickRightFork 表示拿起左边或右边的叉子。 eat 表示吃面。 putLeftFork 和 putRightFork 表示放下左边或右边的叉子。 由于哲学家不是在吃面就是在想着啥时候吃面,所以思考这个方法没有对应的回调。 给你 5 个线程,每个都代表一个哲学家,请你使用类的同一个对象来模拟这个过程。在最后一次调用结束之前,可能会为同一个哲学家多次调用该函数。 解法 前置知识 该问题本质上是线程同步中的死锁问题,常用线程同步方式有互斥锁、条件变量、信号量法;这里使用信号量的方法 P-V信号量 经典的死锁问题解决方案,对于信号量m,P(m)检查m是否为0,为0阻塞,否则将其减1,表示占用资源;V(m)将m加1,表示释放资源 C++方法 sem_init, sem_wait, sem_post 是与信号量(semaphore)相关的函数,常用于进程或线程间的同步。信号量是一种高级的同步机制,用于控制对共享资源的访问数量。 这些函数属于 POSIX 线程库(Pthreads),在多种编程环境中可用,尤其是在 UNIX、Linux 系统中。下面是这些函数的基本用途和如何使用它们的简要说明: sem_init 用途:初始化一个未命名的信号量。 原型 int sem_init(sem_t *sem, int pshared, unsigned int value); sem:指向信号量结构的指针。 pshared:如果这个值非零,信号量在进程间共享;如果为零,信号量只在创建它的进程的所有线程之间共享。 value:信号量的初始值。 sem_wait 用途:减少信号量的值(P 操作)。如果信号量的值为零,则调用线程将被阻塞,直到信号量值大于零。
继续阅读
2024-04-22

长度为n的字符串权重之和

4.21阿里笔试压轴题,状压dp->快速幂,可惜快速幂写错了,三分之一的测试用例因为超时没通过,复盘一下 题目:一个字符串由小写字母组成,其权重定义为不相邻的元音字母(即aeiou)对的个数,例如“aba”的权重为1,请设计程序,计算长度为n的所有字符串的权重之和,答案取模1000000009。 如n=3时,有权重为1的字符串“aaa”“abe”等,这些字符串的权重和为650。 很容易想到dp,而且想求某一特定字符串的权重并不难,但这并不是本题的重点。 经过比较长时间的思考+动笔计算,确定dp方法:dp[i]表示长为i的所有字符串的权重之和,dp[i]=dp[i-1]*26+(i-2)*25*26^(i-2);大概的含义为,i-1字符串的权重和,加上第i个字母结尾的元音对所加入的新权重 #include <bits/stdc++.h> #define MOD 1000000009 using namespace std; long solve(int n); int main() { int n; cin>>n; cout<<solve(n)<<endl; } long solve(int n) { vector<long> dp(n+1, 0); long pow=1; for(int i=3; i<=n; ++i) { pow = pow*26%MOD; dp[i] = (dp[i-1]*26%MOD + (i-2)*25*pow%MOD*26%MOD)%26; } return dp[n]; } 提交,通过66.7%的用例,提示内存过大,于是很容易想到状态压缩: #include <bits/stdc++.h> #define MOD 1000000009 using namespace std; long solve(int n); int main() { int n; cin>>n; cout<<solve(n)<<endl; } long solve(int n) { long pre=0, cur; long pow=1; for(int i=3; i<=n; ++i) { pow = pow*26%MOD; cur = (pre * 26 % MOD + ((i-2) * 25 % MOD) * pow % MOD) % MOD; pre = cur; } return cur;; } 提交,还是只通过66.
继续阅读
2024-04-17

Hive中SQL转化为MapReduce的原理

JOIN操作实现原理 在MapReduce中实现join主要有以下几种方式:Reduce-side join、Map-side join、和Repartition join。下面详细介绍这些方法及其原理。 Reduce-side Join Reduce-side join是MapReduce中最通用的join类型,适用于大规模数据集的连接,特别是当两个数据集都很大且没有任何特殊排序或分区时。 工作原理: Map阶段: Mapper读取两个数据集的所有输入数据(可能来自HDFS的不同文件或目录)。 对每个输入记录,Mapper输出key-value对,其中key是join操作的键,value是包含数据集标识(如标记来自哪个数据集)和数据记录的值。 Shuffle阶段: MapReduce框架将所有Mapper输出的key-value对根据key进行分组和排序,然后分发给Reducers。 Reduce阶段: 每个Reducer接收到特定key的所有记录,这些记录来源于所有的Mapper。Reducer通过检查每条记录的来源数据集标识,将来自不同数据集的记录进行组合。 对于每个key,Reducer执行实际的join逻辑(如inner join, left join等),输出最终的结果。 Map-side Join Map-side join通常在其中一个数据集很小(足够小到可以被加载到内存中)时使用,这种方法效率更高,因为它避免了在Reduce阶段进行大量的数据排序和分组。 工作原理: 预处理阶段: 小的数据集被分发到所有的Mapper节点上,通常通过将其存储在HDFS上并通过DistributedCache机制让每个Mapper节点访问。 Map阶段: 每个Mapper读取大的数据集,并同时加载小的数据集到内存。 Mapper对大数据集的每条记录进行处理,使用内存中的小数据集进行即时join操作。 输出join后的结果。 Repartition Join Repartition join是另一种Reduce-side join的形式,适用于需要特殊排序或分区的场景。 工作原理: 类似于普通的Reduce-side join,但在map阶段会对数据进行额外的分区和排序处理,以优化join的效率。 应用场景 当两个大数据集需要被连接时,使用Reduce-side join。 当一个小数据集可以全局广播到所有Mapper时,使用Map-side join。 当数据需要特殊处理或优化分区时,考虑使用Repartition join。 例如一个Reduce-side Join: select u.name, o.orderid from order o join user u on o.uid = u.uid; 在map的输出value中为不同表的数据打上tag标记,在reduce阶段根据tag判断数据来源。 Group By操作实现原理 Map阶段 任务:读取输入数据,处理记录,并输出键值对。 输出:键是GROUP BY字段,值是需要聚合的数据。 Shuffle阶段 处理:框架自动对Mapper的输出进行排序和分组,确保相同的键被送到同一个Reducer。 Reduce阶段 聚合:Reducer接收到键和对应的值集合,进行数据聚合(如计数、求和)。 结果:输出每个组基于GROUP BY字段的聚合结果。 将GroupBy的字段组合为map的输出key值,利用MapReduce的排序,在reduce阶段保存LastKey区分不同的key。MapReduce的过程如下
继续阅读
2024-04-12

ACM模式C++常用io

自用,ai生成 提前引入头文件 #include <bits/stdc++.h> cin cin是C++中处理标准输入的对象,属于iostream库。它用于从标准输入流(通常是键盘)读取数据。 cin会在等待用户输入时阻塞程序执行。具体来说,它在以下几种情况下会阻塞: 等待输入:当程序到达读取输入的语句,且标准输入中没有足够的数据时,cin会阻塞程序,等待用户输入数据并按下回车键。 输入缓冲区不空,但数据不足:如果输入缓冲区中有一部分数据,但不足以满足当前读取操作的需要,cin同样会阻塞,等待更多输入。 cin用作布尔表达式时,能够反映输入操作的状态: 当输入成功时,cin表达为true。 如果遇到输入结束(EOF),或者输入类型与变量类型不匹配(例如,尝试将字母读入整型变量),cin会表达为false。 cin, 作为C++标准库中的输入流对象,可以用来读取多种基本数据类型,以及一些库中定义的复合类型。这里列出了cin可以直接使用的一些常见数据类型: 基本数据类型 整数类型:int, short, long, long long,以及它们的无符号版本 unsigned int, unsigned short, unsigned long, unsigned long long。 浮点数类型:float, double, long double。 字符类型:char,以及unsigned char和signed char。 布尔类型:bool。 复合类型 字符串:std::string。读取时,cin将会读取并忽略任何前导空格(包括空格、换行符等),然后读取字符直到下一个空白字符为止。 对于大多数基本数据类型(如int、double、char等),cin使用>>操作符读取数据时,会自动跳过任何前导的空白字符,包括空格、制表符和换行符。这意味着如果输入缓冲区的开始是空白字符,cin >>会忽略它们,直到找到第一个非空白字符,并从那里开始读取输入。 getchar() getchar()函数会从输入流中读取下一个字符,并且这个字符会被消耗掉,即它会从输入流中移除,不再可用于后续的输入操作。这意味着一旦getchar()读取了一个字符,这个字符就不会再出现在输入流中,无论是cin、scanf还是其他任何读取标准输入的函数,都无法再次访问到这个字符。 getline() std::getline() 是 C++ 标准库中的一个函数,它用于从输入流中读取一行文本。std::getline() 主要与 std::istream 类型(如 std::cin、文件流等)一起使用,能够从给定的输入流中读取数据直到遇到换行符('\n'),并将读取的内容(不包括换行符)存储到一个 std::string 或其他字符序列中。 std::getline() 有几个重载版本,最常用的两个版本的签名如下: 从标准输入流读取: std::istream& getline(std::istream& is, std::string& str, char delim = '\n'); is: 输入流(如 std::cin 或文件输入流)。 str: 存储从输入流中读取的行的字符串。 delim: 可选参数,指定作为行结束符的字符,默认是换行符 '\n'。函数会读取数据直到遇到此字符为止。 从字符串流读取(属于 <sstream> 头文件):
继续阅读
2024-04-08

Hugo嵌入图片的几种方式

使用Markdown语法 ![图片替代文字](/img/jrqz/trails_in_the_sky_sc.jpg) *图片说明文本* 不支持调整大小 图片说明文本 使用HTML <figure> <img src="/img/jrqz/trails_in_the_sky_sc.jpg" alt="图片替代文字" width="50%"> <figcaption>这里是图片说明</figcaption> </figure> 需要在hugo.toml(config.toml)中添加设置 [markup.goldmark.renderer] unsafe = true 这里是图片说明 可能会导致代码注入等安全问题 使用Hugo短代码 {{< figure src="/img/jrqz/trails_in_the_sky_sc.jpg" caption="这里是图片说明" >}} 更改图片大小需要定义css样式,较为麻烦 这里是图片说明
继续阅读
2024-04-01

基于Hugo的个人博客网站搭建

基于Hugo的个人博客网站,从初始化到申请自己的独立域名,开个博客记录一下 使用Hugo在本地创建个人网站 Hugo是一个基于Go语言的开源的静态网页生成器,以轻量快速闻名,官网链接 安装 平台:Ubuntu 22.04.2 LTS(Windows Subsystem for Linux 2) 安装Go 安装Go,官方教程,安装完成后需要更新PATH,在~/.bashrc文件中添加 export PATH=$PATH:$HOME/go/bin 安装Hugo 这里使用了从源码构建的方法 CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@latest 等待自动安装完毕,检查Hugo是否安装成功 hugo version 创建本地网站 Hugo建站非常简单,只需使用一条命令(将jrqz替换成你的项目名称) hugo new site jrqz 刚建立的网站空空如也,所幸Hugo提供了一系列主题(theme)可供快速上手,这里使用了和官方教程相同的Anake主题 cd jrqz git init git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke echo "theme = 'ananke'" >> hugo.toml 注:在以前的版本中,Hugo的配置文件名为config.toml,网上大部分教程仍旧如此 启动Hugo开发服务器,网站就创建成功了 hugo server 此时可以访问命令行提示的url查看网站 创建第一条博客 Hugo创建博客页面也非常简单,在相应位置下创建Markdown文件,hugo就可以自动将其转化为html页面 hugo new content posts/my-first-post.md 对应的文件可以看到如下内容: +++ title = 'My First Post' date = 2024-03-26T20:32:47+08:00 draft = true +++ draft = true意味着Hugo默认不会发布这篇博客。方便起见,直接将其设置为true
继续阅读
2024-03-27

算法题笔记

C++数据结构用法 通用头文件: #include <bits/stdc++.h> std::list::splice 在C++中,std::list 和 std::forward_list 容器提供了一个名为 splice 的成员函数。这个函数用于在常数时间内从一个列表转移元素到另一个列表,无需复制或移动元素,只是改变节点的指针。这使得 splice 特别高效,适用于需要重组列表元素时不引入额外性能开销的场景。 std::list::splice 函数有几个重载版本,允许你在不同的情况下使用。以下是一些最常用的重载形式: 将整个列表转移到另一个位置: cpp Copy code void splice(const_iterator pos, list& other); 这个版本将 other 列表中的所有元素转移到调用者列表中 pos 位置之前。操作后 other 为空。 将来自另一个列表的单个元素转移到指定位置: cpp Copy code void splice(const_iterator pos, list& other, const_iterator it); 这个版本只转移 other 列表中由迭代器 it 指向的单个元素到调用者列表中 pos 位置之前。 将来自另一个列表的一段元素范围转移到指定位置: cpp Copy code void splice(const_iterator pos, list& other, const_iterator first, const_iterator last); 这个版本将 other 列表中从 first 到 last(不包括 last)的元素转移到调用者列表中 pos 位置之前。
继续阅读
2024-03-26

My First Post

JRQZ的第一篇博客 蔚蓝天空—— 将一切吞噬—— 即使如此命运的齿轮也不会停止转动——
继续阅读
  • ««
  • «
  • 1
  • 2
  • »
  • »»
© JRQZ 2026