专题:一个自制代码生成器(嵌入式脚本语言)之应用实例

news2024/11/25 10:43:09

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


专题:一个自制代码生成器(嵌入式脚本语言)之总述-CSDN博客

专题:一个自制代码生成器(嵌入式脚本语言)之对象模型-CSDN博客

专题:一个自制代码生成器(嵌入式脚本语言)之堆栈结构和总入口-CSDN博客

专题:一个自制代码生成器(嵌入式脚本语言)之核心逻辑-CSDN博客

专题:一个自制代码生成器(嵌入式脚本语言)之辅助逻辑-CSDN博客

专题:一个自制代码生成器(嵌入式脚本语言)之应用实例-CSDN博客(本篇)


目录

一、数据库模型

二、应用实例

2.1 创建模型

2.2 生成代码

2.3 生成的代码

三、如何创建模型


一、数据库模型

        数据库模型是根据数据库定义生成数据库操作相关代码的模型,生成的代码是静态代码,具有静态代码的编译时检查和运行效率。

        数据库模型支持表定义、主键、定制的DML操作。对于C++客户代码,所有操作都是基于函数的,函数名和参数清晰地表达了函数的功能。

        下面我们先了解一个应用实例,然后再研究如何编写模型。

二、应用实例

2.1 创建模型

bool Rooster_AddAllTable(CCTModel_UniversalDB* pCTM)
{
	CCTModel_UniversalDB::table* p;

	//资源类型,预定义的数值
	p = pCTM->AddNewTable("RESOURCE_TYPE_D", "资源类型");
	if (NULL == p)return false;
	p->AddMember("RESOURCE_TYPE_ID", "long", "资源类型");
	p->AddMember("COMMENT", "string", "备注");
	p->SetPK("RESOURCE_TYPE_ID");
	p->AddDML("InsertNewResourceType", "insert", "RESOURCE_TYPE_ID,COMMENT", "", "插入新资源类型");

	//资源使用类型,预定义的数值
	p = pCTM->AddNewTable("RESOURCE_USE_TYPE_D", "资源使用类型");
	if (NULL == p)return false;
	p->AddMember("RESOURCE_USE_TYPE_ID", "long", "资源使用类型ID");
	p->AddMember("COMMENT", "string", "备注");
	p->SetPK("RESOURCE_USE_TYPE_ID");
	p->AddDML("InsertNewResourceUseType", "insert", "RESOURCE_USE_TYPE_ID,COMMENT", "", "插入新资源使用类型");

	//资源
	p = pCTM->AddNewTable("RESOURCE_D", "资源");
	if (NULL == p)return false;
	p->AddMember("RESOURCE_ID", "long", "资源ID");
	p->AddMember("RESOURCE_NAME", "string", "资源名称");
	p->AddMember("RESOURCE_TYPE_ID", "long", "资源类型");
	p->AddMember("RESOURCE_WITH_SYS", "long", "资源是否区分sys/sys2");
	p->AddMember("COMMENT", "string", "备注");
	p->SetPK("RESOURCE_ID");
	p->AddDML("InsertNewResource", "insert", "*", "", "插入新资源");
	p->AddDML("GetAllResource", "select", "*", "", "获得全部");

	//任务定义
	p = pCTM->AddNewTable("TASK_D", "任务");
	if (NULL == p)return false;
	p->AddMember("TASK_ID", "long", "任务ID");
	p->AddMember("TASK_NAME", "string", "任务名称");
	p->AddMember("TASK_MULTIPLE", "long", "0非多开1多开");
	p->AddMember("TASK_WITH_SYS", "long", "是否区分sys/sys2");
	p->AddMember("TASK_PRIORITY", "long", "优先级,小的优先");
	p->AddMember("TASK_PLAN_TIME", "string", "执行时间,‘2,8-16’,时间点或时间段");
	p->AddMember("TASK_PLAN_INTERVAL", "long", "执行时间段的执行间隔(分钟0-59)");
	p->AddMember("TASK_START_CMD", "string", "启动命令");
	p->AddMember("COMMENT", "string", "备注");
	p->SetPK("TASK_ID");
	p->AddDML("InsertNewTaskDefine", "insert", "*", "", "插入新任务定义");
	p->AddDML("GetAllTask", "select", "*", "", "获得全部");

	//任务资源使用定义
	p = pCTM->AddNewTable("TASK_RESOURCE_USE_D", "任务资源使用");
	if (NULL == p)return false;
	p->AddMember("TASK_ID", "long", "任务ID");
	p->AddMember("RESOURCE_ID", "long", "资源ID");
	p->AddMember("RESOURCE_USE_TYPE_ID", "long", "资源使用类型ID");
	p->AddMember("COMMENT", "string", "备注");
	p->SetPK("TASK_ID,RESOURCE_ID");
	p->AddDML("InsertNewTaskResurceUseDefine", "insert", "TASK_ID,RESOURCE_ID,RESOURCE_USE_TYPE_ID,COMMENT", "", "插入新任务资源使用定义");
	p->AddDML("GetAllTaskResourceUse", "select", "*", "", "获得全部");

	//任务队列表
	p = pCTM->AddNewTable("TASK_QUEUE", "待执行的任务队列");
	if (NULL == p)return false;
	p->AddMember("TASK_ID", "long", "任务ID");
	p->AddMember("SYS", "long", "维度1");
	p->AddMember("SYS2", "long", "维度2");
	p->AddMember("TASK_NAME", "string", "任务名称(参考)");
	p->AddMember("TASK_PRIORITY", "long", "优先级,小的优先(参考)");
	p->AddMember("COMMENT", "string", "备注(参考)");
	p->AddMember("INSERT_TIME", "time", "开始时间", "", "TIME_LOG");
	p->SetPK("TASK_ID,SYS,SYS2");
	p->AddDML("InsertNewTaskQueue", "insert", "TASK_ID,SYS,SYS2,TASK_NAME,TASK_PRIORITY,COMMENT,INSERT_TIME", "", "插入新任务队列");
	p->AddDML("DeleteTaskQueue", "delete", "", "TASK_ID,SYS,SYS2", "删除任务队列");
	p->AddDML("GetAllTaskQueue", "select", "*", "", "获取全部任务队列");
	p->AddDML("GetTaskQueue", "select", "*", "TASK_ID,SYS,SYS2", "获取任务队列");

	//任务执行表
	p = pCTM->AddNewTable("TASK_LOG", "任务日志");
	if (NULL == p)return false;
	p->AddMember("TASK_LOG_ID", "long", "任务执行序列号SEQ_TASK_LOG");
	p->AddMember("TASK_ID", "long", "任务ID");
	p->AddMember("SYS", "long", "维度1");
	p->AddMember("SYS2", "long", "维度2");
	p->AddMember("PID", "long", "任务所在的进程,客户方写入");
	p->AddMember("START_TIME", "time", "开始时间", "", "TIME_LOG");
	p->AddMember("FINISH_TIME", "time", "结束时间", "", "TIME_LOG");
	p->AddMember("RETURN_VALUE", "long", "返回值 0成功 <0Rooster错误 >0任务错误");
	p->AddMember("UPDATE_TIME", "time", "记录更新时间", "", "TIME_LOG");
	p->SetPK("TASK_LOG_ID");
	p->AddDML("InsertNewTaskLog", "insert", "TASK_LOG_ID,TASK_ID,SYS,SYS2,START_TIME,UPDATE_TIME", "", "插入新任务日志");
	p->AddDML("UpdateTaskLog", "update", "PID,UPDATE_TIME", "TASK_LOG_ID", "更新任务日志", "finish_time=0");
	p->AddDML("FinishTaskLog", "update", "FINISH_TIME,RETURN_VALUE,UPDATE_TIME", "TASK_LOG_ID", "更新任务日志", "finish_time=0");
	p->AddDML("GetCurrentTask", "select", "*", "", "获取正在运行的任务", "finish_time=0");

	//序列
	if (NULL == pCTM->AddNewSequence("SEQ_TASK_LOG", "TASK日志序列", 0))return false;

	return true;
}

        这个代码创建了一组表和一个序列,每一行代码的功能都是显而易见的。

2.2 生成代码

int main(int argc, char** argv)
{
	if (!InitActiveApp("CCTModel_UniversalDB", 1024 * 1024, argc, argv))exit(1);

	if (sizeof(long) != 8)
	{
		thelog << "非64位程序!" << ende;
	}

	G_IS_DEBUG = true;

	CCTModel_UniversalDB ctm;
	if (!Rooster_AddAllTable(&ctm))
	{
		thelog << "执行失败" << ende;
		return __LINE__;
	}
	if (!ctm.CreateCode("ns_rooster_struct", "RoosterStruct", "."))
	{
		thelog << "执行失败" << ende;
		return __LINE__;
	}

	thelog << "程序退出" << endi;
	return 0;
}

        有用的就两句:Rooster_AddAllTable创建模型,CreateCode生成代码。

2.3 生成的代码

        生成的一组文件:

        总入口头文件是_cc_CRoosterStruct.h:

//_cc_CRoosterStruct.h 自动生成的代码
//
// Copyright (c) ct  All rights reserved.
// 版权所有 ct 保留所有权利
//

//警告:本文件由CT系统自动生成,不可手工修改

#ifndef CTFC_RoosterStruct_H
#define CTFC_RoosterStruct_H 1

//如果需要使用内存数据库直连功能,请在包含本头文件之前定义 CTFC_RoosterStruct_H_SHM_DB
//如果需要使用MariaDB功能,请在包含本头文件之前定义 CTFC_RoosterStruct_H_MARIA_DB
#include "_cc_RoosterStruct_RESOURCE_TYPE_D.h"
#include "_cc_RoosterStruct_RESOURCE_USE_TYPE_D.h"
#include "_cc_RoosterStruct_RESOURCE_D.h"
#include "_cc_RoosterStruct_TASK_D.h"
#include "_cc_RoosterStruct_TASK_RESOURCE_USE_D.h"
#include "_cc_RoosterStruct_TASK_QUEUE.h"
#include "_cc_RoosterStruct_TASK_LOG.h"
#include "_cc_RoosterStruct_SEQ_TASK_LOG.h"

using namespace ns_my_std;

namespace ns_rooster_struct
{
	class CShmDB_RoosterStruct
	{
	public:
		//表
		CRoosterStruct_RESOURCE_TYPE_D m_RESOURCE_TYPE_D;//资源类型
		CRoosterStruct_RESOURCE_USE_TYPE_D m_RESOURCE_USE_TYPE_D;//资源使用类型
		CRoosterStruct_RESOURCE_D m_RESOURCE_D;//资源
		CRoosterStruct_TASK_D m_TASK_D;//任务
		CRoosterStruct_TASK_RESOURCE_USE_D m_TASK_RESOURCE_USE_D;//任务资源使用
		CRoosterStruct_TASK_QUEUE m_TASK_QUEUE;//待执行的任务队列
		CRoosterStruct_TASK_LOG m_TASK_LOG;//任务日志

		//序列
		CRoosterStruct_SEQ_TASK_LOG m_SEQ_TASK_LOG;//TASK日志序列
	public:
#ifdef CTFC_RoosterStruct_H_SHM_DB
#define CTFC_RoosterStruct_H_WITH_DB
		typedef CShmDB T_DB;
#endif

#ifdef CTFC_RoosterStruct_H_MARIA_DB
#define CTFC_RoosterStruct_H_WITH_DB
		typedef CMariaDB T_DB;
#endif
	private:
#ifdef CTFC_RoosterStruct_H_WITH_DB
		T_DB m_ShmDB;
		T_DB * pDB;
#endif
	public:
#ifdef CTFC_RoosterStruct_H_WITH_DB
		//返回内部数据库对象
		T_DB * getDB(){return pDB;}
		//直连初始化
		bool DBInit(char const * db = nullptr)
		{
#ifdef CTFC_RoosterStruct_H_SHM_DB
			CShmActiveObjects * p;
			p = m_ShmDB.GetCShmActiveObjects();
			if (!p->isConnected() && !p->Attach(false))
#endif
#ifdef CTFC_RoosterStruct_H_MARIA_DB
			if(!m_ShmDB.Connect(db))
#endif
			{
				thelog << "CRoosterStruct连接失败" << ende;
				return false;
			}
			DEBUG_LOG << "CRoosterStruct连接成功" << endi;

			pDB = &m_ShmDB;
			
			m_RESOURCE_TYPE_D.Init(pDB);
			m_RESOURCE_USE_TYPE_D.Init(pDB);
			m_RESOURCE_D.Init(pDB);
			m_TASK_D.Init(pDB);
			m_TASK_RESOURCE_USE_D.Init(pDB);
			m_TASK_QUEUE.Init(pDB);
			m_TASK_LOG.Init(pDB);

			m_SEQ_TASK_LOG.Init(pDB);

			return true;
		}
		//直连断开
		bool DBUnInit()
		{
#ifdef CTFC_RoosterStruct_H_SHM_DB
			CShmActiveObjects * p;
			p = m_ShmDB.GetCShmActiveObjects();
			if (p->isConnected())p->Detach();
#endif
#ifdef CTFC_RoosterStruct_H_MARIA_DB
			pDB->Close();
#endif
			pDB = NULL;
			return true;
		}
		//直连创建所有数据库对象
		bool DBCreateAllDBObject()
		{
			//创建表
			if(!m_RESOURCE_TYPE_D.CreateTable())return false;
			if(!m_RESOURCE_USE_TYPE_D.CreateTable())return false;
			if(!m_RESOURCE_D.CreateTable())return false;
			if(!m_TASK_D.CreateTable())return false;
			if(!m_TASK_RESOURCE_USE_D.CreateTable())return false;
			if(!m_TASK_QUEUE.CreateTable())return false;
			if(!m_TASK_LOG.CreateTable())return false;

			//创建序列
			if(!m_SEQ_TASK_LOG.CreateSequence())return false;

			return true;
		}
		//直连显示所有数据库对象
		bool DBShowAllDBObject()
		{
			//显示表
			if(!m_RESOURCE_TYPE_D.Show())return false;
			if(!m_RESOURCE_USE_TYPE_D.Show())return false;
			if(!m_RESOURCE_D.Show())return false;
			if(!m_TASK_D.Show())return false;
			if(!m_TASK_RESOURCE_USE_D.Show())return false;
			if(!m_TASK_QUEUE.Show())return false;
			if(!m_TASK_LOG.Show())return false;

			//显示序列
			thelog << "sequence:" << endl << "-------------------------" << endl;
			theLog<< "SEQ_TASK_LOG " << m_SEQ_TASK_LOG.GetSequenceValue() << endl;
			theLog << "-------------------------" << endi;

			return true;
		}
#endif
	};
}
#endif

        这个文件看起来和普通手写的文件没有任何区别,除了它真的是用代码模板生成的。

        再来看看生成这个文件的模板_t_UniversalDB.h.ct是什么样的:

//_cc_C${SYS}.h 自动生成的代码
//
// Copyright (c) ct  All rights reserved.
// 版权所有 ct 保留所有权利
//

//警告:本文件由CT系统自动生成,不可手工修改

#ifndef CTFC_${SYS}_H
#define CTFC_${SYS}_H 1

//如果需要使用内存数据库直连功能,请在包含本头文件之前定义 CTFC_${SYS}_H_SHM_DB
//如果需要使用MariaDB功能,请在包含本头文件之前定义 CTFC_${SYS}_H_MARIA_DB
<%foreach table in ${tables}%>
#include "_cc_${SYS}_${table}.h"
<%endforeach%>
<%foreach sequence in sequences%>
#include "_cc_${SYS}_${sequence}.h"
<%endforeach%>

using namespace ns_my_std;

namespace ${NAMESPACE}
{
	class CShmDB_${SYS}
	{
	public:
		//表
		<%foreach table in tables%>
		C${SYS}_${table} m_${table};//${table.comment}
		<%endforeach%>

		//序列
		<%foreach sequence in sequences%>
		C${SYS}_${sequence} m_${sequence};//${sequence.comment}
		<%endforeach%>
	public:
#ifdef CTFC_${SYS}_H_SHM_DB
#define CTFC_${SYS}_H_WITH_DB
		typedef CShmDB T_DB;
#endif

#ifdef CTFC_${SYS}_H_MARIA_DB
#define CTFC_${SYS}_H_WITH_DB
		typedef CMariaDB T_DB;
#endif
	private:
#ifdef CTFC_${SYS}_H_WITH_DB
		T_DB m_ShmDB;
		T_DB * pDB;
#endif
	public:
#ifdef CTFC_${SYS}_H_WITH_DB
		//返回内部数据库对象
		T_DB * getDB(){return pDB;}
		//直连初始化
		bool DBInit(char const * db = nullptr)
		{
#ifdef CTFC_${SYS}_H_SHM_DB
			CShmActiveObjects * p;
			p = m_ShmDB.GetCShmActiveObjects();
			if (!p->isConnected() && !p->Attach(false))
#endif
#ifdef CTFC_${SYS}_H_MARIA_DB
			if(!m_ShmDB.Connect(db))
#endif
			{
				thelog << "C${SYS}连接失败" << ende;
				return false;
			}
			DEBUG_LOG << "C${SYS}连接成功" << endi;

			pDB = &m_ShmDB;
			
			<%foreach table in tables%>
			m_${table}.Init(pDB);
			<%endforeach%>

			<%foreach sequence in sequences%>
			m_${sequence}.Init(pDB);
			<%endforeach%>

			return true;
		}
		//直连断开
		bool DBUnInit()
		{
#ifdef CTFC_${SYS}_H_SHM_DB
			CShmActiveObjects * p;
			p = m_ShmDB.GetCShmActiveObjects();
			if (p->isConnected())p->Detach();
#endif
#ifdef CTFC_${SYS}_H_MARIA_DB
			pDB->Close();
#endif
			pDB = NULL;
			return true;
		}
		//直连创建所有数据库对象
		bool DBCreateAllDBObject()
		{
			//创建表
			<%foreach table in tables%>
			if(!m_${table}.CreateTable())return false;
			<%endforeach%>

			//创建序列
			<%foreach sequence in sequences%>
			if(!m_${sequence}.CreateSequence())return false;
			<%endforeach%>

			return true;
		}
		//直连显示所有数据库对象
		bool DBShowAllDBObject()
		{
			//显示表
			<%foreach table in tables%>
			if(!m_${table}.Show())return false;
			<%endforeach%>

			//显示序列
			thelog << "sequence:" << endl << "-------------------------" << endl;
			<%foreach sequence in sequences%>
			theLog<< "${sequence} " << m_${sequence}.GetSequenceValue() << endl;
			<%endforeach%>
			theLog << "-------------------------" << endi;

			return true;
		}
#endif
	};
}
#endif

        这就是一个代码模板编写的典型例子,用到了大量的循环处理和变量替换。看起来像asp?嗯,就是模仿asp啊。

三、如何创建模型

        下一篇将详细解释这个模型(原则上,除了最终生成的的是这个脚本生成器要求的对象结构外模型和脚本生成器并没有更多关联)。


(这里是结束,但不是整个系列的结束)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1552883.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【嵌入式机器学习开发实战】(十二)—— 政安晨:通过ARM-Linux掌握基本技能【C语言程序的安装运行】

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 嵌入式机器学习开发实战 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 在ARM-Linux系统中&#xff0c;C语言程序的安装和运行可…

局域网找不到共享电脑怎么办?

局域网找不到共享电脑是一种常见的问题&#xff0c;给我们的共享与合作带来一定的困扰。天联组网技术可以解决这个问题。本文将介绍天联组网的原理和优势&#xff0c;并探讨其在解决局域网找不到共享电脑问题中的应用。 天联组网的原理和优势 天联组网是一种基于加速服务器的远…

Linux 系统 CentOS7 上搭建 Hadoop HDFS集群详细步骤

集群搭建 整体思路:先在一个节点上安装、配置,然后再克隆出多个节点,修改 IP ,免密,主机名等 提前规划: 需要三个节点,主机名分别命名:node1、node2、node3 在下面对 node1 配置时,先假设 node2 和 node3 是存在的 **注意:**整个搭建过程,除了1和2 步,其他操作都使…

浅谈C语言编译与链接

个人主页&#xff08;找往期文章包括但不限于本期文章中不懂的知识点&#xff09;&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 翻译环境和运行环境 在ANSI C&#xff08;标准 C&#xff09;的任何一种实现中&#xff0c;存在两个不同的环境。 第1种是翻译环境&#xff0c;在这个…

XUbuntu22.04之激活Linux最新Typora版本(二百二十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

109、Recent Advances in 3D Gaussian Splatting

简介 论文 对3D Gaussian Splatting的综述 质量提升 Mip-Splatting观察到&#xff0c;改变采样率&#xff0c;例如焦距&#xff0c;可以通过引入高频高斯类形伪影或强膨胀效应&#xff0c;极大地影响渲染图像的质量&#xff0c;因此Mip-Splatting将3D表示的频率限制在训练图…

IP种子是什么?理解和应用

在网络世界中&#xff0c;IP种子是一个广泛应用于文件共享和网络下载领域的概念。它是一种特殊的标识符&#xff0c;用于识别和连接到基于对等网络&#xff08;P2P&#xff09;协议的文件共享网络中的用户或节点。本文将深入探讨IP种子的含义、作用以及其在网络中的应用。 IP地…

计算机网络:物理层 - 信道极限容量

计算机网络&#xff1a;物理层 - 信道极限容量 实际信道中的数字信号奈式准则香农公式练习 实际信道中的数字信号 信号在传输过程中会受到各种因素的影响&#xff0c;如图所示&#xff1a; 这是一个数字信号&#xff0c;当它通过实际的信道后&#xff0c;波形会产生失真&#…

C语言例4-36:求Fibonacci数列的前40个数

教材优化代码如下&#xff1a; //求Fibonacci数列的前40个数 #include<stdio.h> int main(void) {long int f11,f21;int i1;for(;i<20;i){printf("%15ld%15ld",f1,f2);if(i%20)printf("\n");f1f2;f2f1;}return 0; } 结果如下&#xff1a; 我的基…

php 快速入门(七)

一、操作数据库 1.1 操作MySQL的步骤 第一步&#xff1a;登录MySQL服务器 第二步&#xff1a;选择当前数据库 第三步&#xff1a;设置请求数据的字符集 第四步&#xff1a;执行SQL语句 1.2 连接MySQL 函数1&#xff1a;mysql_connect() 功能&#xff1a;连接&#xff08;登录…

Netty对Channel事件的处理以及空轮询Bug的解决

继续上一篇Netty文章&#xff0c;这篇文章主要分析Netty对Channel事件的处理以及空轮询Bug的解决 当Netty中采用循环处理事件和提交的任务时 由于此时我在客户端建立连接&#xff0c;此时服务端没有提交任何任务 此时select方法让Selector进入无休止的阻塞等待 此时selectCnt进…

【计算机网络】第 11、12 问:流量控制和可靠传输机制有哪些?

目录 正文流量控制的基本方法停止-等待流量控制基本原理滑动窗口流量控制基本原理 可靠传输机制1. 停止-等待协议2. 后退 N 帧协议&#xff08;GBN&#xff09;3. 选择重传协议&#xff08;SR&#xff09; 正文 流量控制涉及对链路上的帧的发送速率的控制&#xff0c;以使接收…

zabbix自定义监控进程、日志文件

zabbix自定义监控进程、日志文件 zabbix自定义监控进程 在客户端安装httpd服务 [rootnode1 ~]# yum -y install httpd [rootnode1 ~]# systemctl start httpd [rootnode1 ~]# ss -antl State Recv-Q Send-Q Local Address:Port Peer Address:Port Pr…

【Redis】Redis 内存管理,Redis事务,bigkey和hotkey

目录 Redis 内存管理 缓存数据设置过期时间&#xff1f; Redis 是如何判断数据是否过期的呢&#xff1f; 过期删除策略 内存淘汰机制 主从模式下对过期键的处理&#xff1f; LRU和LFU的区别 Redis事务 定义和原理 Redis 事务的注意点&#xff1f; 为什么不支持回滚&a…

shell脚本发布docker-nginx vue2 项目示例

docker、git、node.js安装略过。 使git pull或者git push不需要输入密码操作方法 nginx安装在docker容器里面&#xff0c;参见&#xff1a;https://blog.csdn.net/HSJ0170/article/details/128631155 姊妹篇&#xff08;宿主机nginx&#xff0c;非docker-nginx&#xff09;&am…

React 应用实现监控可观测性最佳实践

前言 React 是一个用于构建用户界面的 JavaScript 框架。它采用了虚拟 DOM 和 JSX&#xff0c;提供了一种声明式的、组件化的编程模型&#xff0c;以便更高效地构建用户界面。无论是简单还是复杂的界面&#xff0c;React 都可以胜任。 YApi 是使用 React 编写的高效、易用、功…

StarRocks实战——多点大数据数仓构建

目录 前言 一、背景介绍 二、原有架构的痛点 2.1 技术成本 2.2 开发成本 2.2.1 离线 T1 更新的分析场景 2.2.2 实时更新分析场景 2.2.3 固定维度分析场景 2.2.4 运维成本 三、选择StarRocks的原因 3.1 引擎收敛 3.2 “大宽表”模型替换 3.3 简化Lambda架构 3.4 模…

“预防儿童烧烫伤”科普安全课堂走进嘉鱼县第一小学

为提高嘉鱼县儿童烧烫伤安全意识、隐患识别能力以及突发应急处置能力&#xff0c;3月26日下午&#xff0c;在中国社会福利基金会烧烫伤关爱公益基金、嘉鱼县妇女联合会、嘉鱼县教育局的支持下&#xff0c;嘉鱼县蒲公英社会工作服务中心走进嘉鱼县第一小学开展预防儿童烧烫伤科普…

图论之路径条数专题

一直忙着金工实习蓝桥杯&#xff0c;好久没有看图论了&#xff0c;今天就小试几题享受下被虐的快感。 1.最短路拓扑 首先来几个结论&#xff1a; 1.最短路图没有环&#xff08;可以用反证法证明&#xff09; 2.dis[u]edge[u,v]dis[v]&#xff0c;那么u,v端点的边一定在最短路…

【笔记】RDD算子操作(Spark基础知识)

持续更新中&#xff01;&#xff01;&#xff01; 目录 一、RDD的创建 1.从本地创建 &#xff08;1&#xff09;本地文件 &#xff08;2&#xff09;hdfs文件&#xff08;先提前创建目录并上传文件&#xff09; 2.从集合创建&#xff08;通过并行集合&#xff08;列表&am…