diff --git a/cdh/CDH部署Kerberos.md b/cdh/CDH部署Kerberos.md index 3f989ba..360a4da 100644 --- a/cdh/CDH部署Kerberos.md +++ b/cdh/CDH部署Kerberos.md @@ -298,3 +298,13 @@ kinit -r 参数后面指定的时间 - baseDN 登录用户组 - project用户组可以登录hive - **ou=project**,dc=yldev,dc=net + + + + + + +## 获取特权keytab + +创建 hdfs@A.COM +获取密钥 然后认证 即可使用特权hdfs账号 操作 hdfs 文件系统 diff --git a/cdh/合并keytab.md b/cdh/合并keytab.md new file mode 100644 index 0000000..7b87e44 --- /dev/null +++ b/cdh/合并keytab.md @@ -0,0 +1,52 @@ +### 操作步骤: + +1. **准备工作**:确保所有需要合并的 keytab 文件(如 `user1.keytab`、`service.keytab` 等)都在当前目录,且系统已安装 Kerberos 客户端工具(含 `ktutil`)。 + +2. **启动 `ktutil` 交互式工具**: + + ```bash +ktutil + ``` + +3. **加载需要合并的 keytab 文件**: + 依次输入以下命令,将每个 keytab 文件加载到内存中(替换文件名为实际文件): + + ```bash + ktutil: read_kt user1.keytab # 加载第一个 keytab + ktutil: read_kt service.keytab # 加载第二个 keytab + ktutil: read_kt app.keytab # 加载更多 keytab(如有) + ``` + +4. **验证加载的密钥条目**: + 输入 `list` 命令查看已加载的所有主体和密钥信息,确认是否正确: + + ```bash + ktutil: list + ``` + +5. **将所有条目写入新的合并 keytab 文件**: + 输入以下命令,将内存中的所有密钥写入一个新文件(如 `merged.keytab`): + + ```bash + ktutil: write_kt merged.keytab + ``` + +6. **退出工具**: + + ```bash +ktutil: quit + ``` + + + + + +### 验证合并结果: + +使用 `klist` 命令检查合并后的 keytab 是否包含所有主体: + +```bash +klist -k merged.keytab +``` + +如果输出包含所有原始 keytab 中的主体,则合并成功。 \ No newline at end of file diff --git a/java/先序遍历原理.md b/java/先序遍历原理.md new file mode 100644 index 0000000..c90f69c --- /dev/null +++ b/java/先序遍历原理.md @@ -0,0 +1,192 @@ +# 先序遍历原理:从树结构到实际应用的深度解析 +先序遍历(Pre-order Traversal)是树结构中最基础、最常用的遍历方式之一,其核心思想是“先访问根节点,再递归遍历左子树,最后递归遍历右子树”。在部门树形结构等场景中,先序遍历的衍生设计(如左值右值标记法)能极大提升数据操作效率。以下从基础概念到实际应用展开详细解说。 + + +## 一、先序遍历的基础定义与核心规则 +### 1. 树结构的基本概念 +在讲解先序遍历前,需明确树的核心术语: +- **节点**:树中的每个元素(如部门树形结构中的“部门”)。 +- **根节点**:树的顶层节点(无父节点,如公司总部)。 +- **子节点**:被父节点直接包含的节点(如“技术部”是“研发中心”的子节点)。 +- **叶子节点**:无任何子节点的节点(如“前端开发组”)。 +- **路径**:从根节点到某一节点的所有节点组成的序列。 + +### 2. 先序遍历的核心逻辑 +先序遍历的遍历顺序可概括为 **“根 → 左 → 右”**,即: +1. 首先访问当前节点(记录或处理节点信息); +2. 递归地对当前节点的**左子树**执行先序遍历; +3. 递归地对当前节点的**右子树**执行先序遍历。 + +#### 示例:二叉树的先序遍历 +对如下二叉树(A为根节点,B、C为子节点): +``` + A + / \ + B C + / \ +D E +``` +先序遍历顺序为: +**A → B → D → E → C** +- 访问根节点A → 遍历左子树B → 访问B → 遍历B的左子树D → 访问D(无左右子树)→ 遍历B的右子树E → 访问E → 左子树遍历完成 → 遍历根节点A的右子树C → 访问C。 + + +## 二、多叉树的先序遍历(部门树场景适配) +部门树等实际场景中,树通常是**多叉树**(一个父节点可包含多个子节点),先序遍历规则调整为: +**“根 → 子树1 → 子树2 → ... → 子树n”**,即访问根节点后,按顺序递归遍历每个子树。 + +### 1. 多叉树先序遍历示例 +以某公司部门树为例(根节点为“总公司”,下设“技术部”“市场部”,技术部下设“前端组”“后端组”): +``` + 总公司(根节点) + / \ + 技术部 市场部 + / \ +前端组 后端组 +``` +先序遍历顺序为: +**总公司 → 技术部 → 前端组 → 后端组 → 市场部** +- 访问总公司 → 遍历第一个子树“技术部” → 访问技术部 → 遍历技术部第一个子树“前端组” → 访问前端组(无子节点)→ 遍历技术部第二个子树“后端组” → 访问后端组 → 技术部子树遍历完成 → 遍历总公司第二个子树“市场部” → 访问市场部。 + + +## 三、先序遍历在部门树存储中的核心应用:左值(lft)与右值(rgt)标记 +在部门树形结构存储优化中,先序遍历的核心价值在于通过**“进入标记”和“离开标记”** 记录节点的层级关系,即左值(lft)和右值(rgt)的设计。 + +### 1. 标记规则 +遍历过程中,每个节点会被标记两个值: +- **左值(lft)**:首次访问节点(进入节点)时记录的序号(从1开始递增); +- **右值(rgt)**:遍历完该节点的**所有子节点**后(离开节点)记录的序号。 + +### 2. 标记示例(基于上述部门树) +| 遍历步骤 | 操作 | 节点 | lft值 | rgt值 | +|----------------|---------------|------------|-------|-------| +| 1 | 进入根节点 | 总公司 | 1 | - | +| 2 | 进入子节点 | 技术部 | 2 | - | +| 3 | 进入子节点 | 前端组 | 3 | - | +| 4 | 离开前端组(无子节点) | 前端组 | - | 4 | +| 5 | 进入子节点 | 后端组 | 5 | - | +| 6 | 离开后端组(无子节点) | 后端组 | - | 6 | +| 7 | 离开技术部(所有子节点遍历完成) | 技术部 | - | 7 | +| 8 | 进入子节点 | 市场部 | 8 | - | +| 9 | 离开市场部(无子节点) | 市场部 | - | 9 | +| 10 | 离开总公司(所有子节点遍历完成) | 总公司 | - | 10 | + +最终标记结果: +| 节点 | lft | rgt | +|------------|-----|-----| +| 总公司 | 1 | 10 | +| 技术部 | 2 | 7 | +| 前端组 | 3 | 4 | +| 后端组 | 5 | 6 | +| 市场部 | 8 | 9 | + +### 3. 核心规律(标记的价值所在) +通过先序遍历标记的lft和rgt,形成以下关键规律,支撑高效查询: +- **父子关系**:父节点的lft < 所有子节点的lft,且父节点的rgt > 所有子节点的rgt(如总公司lft=1 < 技术部lft=2,rgt=10 > 技术部rgt=7)。 +- **子孙范围**:一个节点的所有子孙节点,其lft和rgt均在该节点的lft和rgt之间(如技术部的子孙节点前端组、后端组,lft均在2-7之间)。 +- **叶子节点特征**:叶子节点无子孙,因此rgt = lft + 1(如前端组lft=3,rgt=4=3+1)。 +- **子孙数量计算**:某节点的子孙总数 = (rgt - lft - 1) / 2(如技术部子孙数=(7-2-1)/2=2,即前端组和后端组)。 + + +## 四、先序遍历的优缺点与适用场景 +### 1. 优势 +- **查询效率极高**:基于lft和rgt的规律,无需递归即可快速查询子孙节点、计算数量、判断叶子节点等,时间复杂度低。 +- **关系表达直观**:通过数值范围直接体现层级关系,避免传统parent_id的链式依赖。 + +### 2. 局限性 +- **维护成本高**:新增或删除节点时,需批量更新后续节点的lft和rgt(如插入一个节点需给所有lft大于插入位置的节点+2),数据量大时操作耗时。 +- **初始化复杂**:现有树形结构迁移时需全量遍历计算lft和rgt,层级过深或数据量大时成本高。 + +### 3. 适用场景 +最适合**查询频繁、结构稳定、数据量中等**的树形场景,如: +- 企业组织架构(部门层级变动少,查询需求多); +- 权限菜单树(菜单结构稳定,需频繁查询子菜单); +- 分类目录树(如电商商品分类,查询远多于增删)。 + + +## 五、总结 +先序遍历作为树结构的基础遍历方式,其核心是“先根后子”的访问顺序。在部门树等场景中,通过衍生的lft和rgt标记法,将树形关系转化为数值范围关系,实现了查询效率的质的提升。理解先序遍历的原理,不仅能掌握这一优化方案的核心逻辑,更能深入理解树形数据结构在计算机存储与操作中的设计思想。实际应用中需结合业务的查询与写入频率、数据量大小,权衡其优势与维护成本,避免盲目套用。 + + + +## 六、附 + +查出所有子孙部门 + +```sql +SET @lft := 9; +SET @rgt := 18; +SELECT * FROM department WHERE lft BETWEEN @lft AND @rgt ORDER BY lft ASC; +/*例子中用BETWEEN将被查部门本身也查了出来。实际中可以用大于小于*/ +``` + +查询子孙部门总数 + +``` +总数 = (右值 - 左值 - 1) / 2 +``` + +新增部门 + +```sql +SET @lft := 7;/*新部门的左值*/ +SET @rgt := 8;/*新部门的左值*/ +SET @level := 5;/*新部门的层级*/ +begin; +/*将插入的后续边缘的节点左右数+2*/ +UPDATE department SET lft=lft+2 WHERE lft > @lft; +UPDATE department SET rgt=rgt+2 WHERE rgt >= @lft; +/*插入数据*/ +INSERT INTO department(name,lft,rgt,level) VALUES('新部门',@lft,@rgt,level); +/*新增影响行数为0时,必须回滚*/ +commit; +/*rollback;*/ +``` + +删除 + +```sql +SET @lft := 7;/*要删除的节点左值*/ +SET @rgt := 8;/*要删除的节点右值*/ +begin; +UPDATE department SET lft=lft-2 WHERE lft > @lft; +UPDATE department SET rgt=rgt-2 WHERE rgt > @lft; + +/*删除节点*/ +DELETE FROM department WHERE lft=@lft AND rgt=@rgt; +/*删除影响行数为0时,必须回滚*/ +commit; +``` + +直接子节点 + +```sql +SET @level := 2;/*总经理的level*/ +SET @lft := 2;/*总经理的左值*/ +SET @rgt := 19;/*总经理的右值*/ + +SELECT * FROM department WHERE lft > @lft AND rgt < @rgt AND level = @level+1; +``` + +祖宗链路 + +```sql +SET @lft := 3;/*产品部左值*/ +SET @rgt := 8;/*产品部右值*/ + +SELECT * FROM department WHERE lft < @lft AND rgt > @rgt ORDER BY lft ASC; +``` + +计算层级 + +```sql +-- 统计祖链节点数量,再加1即为当前节点层级 +SELECT COUNT(*) + 1 AS level +FROM department +WHERE lft < 3 AND rgt > 4; +``` + +``` +直接存储 层级 +``` +