GraphQL的力量:简化复杂数据查询

在这里插入图片描述

1. GraphQL

GraphQL 是一种由 Facebook 开发并于 2015 年公开发布的数据查询和操作语言,也是运行在服务端的运行时(runtime)用于处理 API 查询的一种规范。不同于传统的 REST API,GraphQL 允许客户端明确指定它们需要哪些数据,因此可以避免过度获取或者获取不足的问题。

GraphQL 有以下几个核心概念:

  1. 查询 (Query): 类似于 GET 请求,用于获取数据。
  2. 变更 (Mutation): 类似于 POST、PUT、DELETE 等请求,用于修改数据。
  3. 订阅 (Subscription): 允许客户端实时地获取数据更新。
  4. 类型系统 (Type System): GraphQL 使用强类型系统,API 中的每个数据都有一个预定义的类型。

2. 诞生背景

在 GraphQL 出现之前,RESTful API 是构建网络应用程序中客户端与服务器之间通信的主流方式。随着移动设备和复杂单页应用(SPA)的兴起,应用程序的接口需求变得越来越复杂。REST 接口在某些场景中开始显现出一些不足之处:

  1. 过度获取 (Over-fetching): 获取比客户端实际需要更多的数据。一个 RESTful 请求通常返回一个固定结构的数据对象,如果客户端只需要其中的几个字段,也要接收整个对象。

  2. 获取不足 (Under-fetching): 得到的数据不足以满足客户端的需要,导致客户端不得不发送多个请求以获取所有所需数据。在 RESTful 架构中,这通常发生在服务端资源高度正规化时,客户端需要通过多个端点组装所需的数据。

  3. 多版本并存: 随着时间的推移,为了满足不同客户端的特定需求,可能会出现多个版本的 API 并存。

  4. 前后端协作: 在 RESTful 架构下,前端开发者常常需要后端对 API 进行调整以适应界面的需求变化,这增加了协作的复杂性。

3. GraphQL 的解决方式

GraphQL 通过其设计和特性提供了解决传统 REST API 问题的方法。以下是具体问题及其解决方式:

  1. 过度获取 (Over-fetching):

    • 解决方法: 在 GraphQL 中,客户端可以准确指定它们需要的字段,并且只有这些指定的字段会返回给客户端。这意味着客户端永远不会收到多余的数据,从而减少了不必要的数据传输和提高了性能。
  2. 获取不足 (Under-fetching):

    • 解决方法: GraphQL 允许客户端在单个查询中请求所有必需的信息,即使这些信息分布在不同的“资源”或实体中。这样客户端只需要发起一个网络请求,就可以获取到完整的、它们所需的数据集合。
  3. 多版本并存:

    • 解决方法: GraphQL 只需要一个版本的 API。由于客户端可以精确地请求它们需要的数据,所以后端只需不断迭代其 GraphQL schema 而无需担心会破坏现有客户端。这样,客户端和服务器可以独立进化而不会互相影响。
  4. 前后端协作:

    • 解决方法: 在 GraphQL 中,由于存在一个明确的类型系统,前端工程师可以独立于后端工程师根据需求构造查询。这减少了前后端之间的沟通成本,使前端开发者能够更加自由地开发和迭代产品,而无需等待后端调整 API。

具体来说,GraphQL 解决这些问题的一些关键特性包括:

  • 强类型系统 (Type System): GraphQL 的每一个 API 都基于强类型定义的 schema,这样就为自动生成文档、前后端的协同开发以及工具链的构建提供了坚实的基础。

  • 声明式数据获取: 客户端使用 GraphQL 的查询语言来声明它们所需的数据结构,并且服务端正好按照这种结构返回数据。这样做的好处是,无论数据需求如何变化,只要服务端的 schema 支持,客户端可以自行调整查询,而无需服务端进行修改。

  • 单一端点: 与 REST API 不同的是,GraphQL 通常只有一个端点,所有的查询和变更都通过这个端点发起。这消除了处理多个端点可能导致的复杂性。

  • 查询组合: GraphQL 查询可以很容易地组合在一起,即使它们涉及到不同的资源类型,客户端还可以在一个查询中请求关联数据。

通过这样一套机制,GraphQL 提供了比传统 RESTful API 更灵活、可扩展的数据交互方式,满足现代应用开发对接口灵活性和效率的要求。

5. 引入 graphQL 在服务端的变化

引入 GraphQL 后,后端开发会有一系列的变化,从设置服务器开始,到重新设计数据获取的方式,再到实现复杂的解析逻辑。以下是引入 GraphQL 后可能需要做的改动:

1. 设置 GraphQL 服务器

首先,你需要引入 GraphQL 相关的库,并设置一个 GraphQL 服务器,这通常意味着要添加一个新的端点来处理 GraphQL 请求。

:RESTful API 服务器示例(使用 Express.js)

const express = require("express");
const app = express();

app.get("/api/books/:id", (req, res) => {
  // 根据 id 获取书籍信息的逻辑
});

app.listen(3000, () => {
  console.log("Server running on port 3000");
});

:GraphQL 服务器示例(使用 Express.js + express-graphql)

const express = require("express");
const { graphqlHTTP } = require("express-graphql");
const { buildSchema } = require("graphql");

const schema = buildSchema(`
  type Query {
    book(id: ID!): Book
  }

  type Book {
    id: ID!
    title: String!
    author: String!
  }
`);

const root = {
  book: ({ id }) => {
    // 根据 id 获取书籍信息的逻辑
  },
};

const app = express();
app.use(
  "/graphql",
  graphqlHTTP({
    schema,
    rootValue: root,
    graphiql: true,
  })
);

app.listen(3000, () => {
  console.log("GraphQL server running on port 3000");
});

2. 重新设计 API Schema

你需要根据业务数据设计 GraphQL schema,这通常涉及定义查询和变更类型、数据模型类型以及它们之间的关系。

:RESTful API 设计通常是基于资源的 URL 设计

  • GET /api/books/:id
  • POST /api/books
  • PUT /api/books/:id
  • DELETE /api/books/:id

:GraphQL 中只有单一端点,schema 定义了所有的查询和变更

type Query {
  book(id: ID!): Book
}

type Mutation {
  createBook(title: String!, author: String!): Book
  updateBook(id: ID!, title: String, author: String): Book
  deleteBook(id: ID!): Book
}

type Book {
  id: ID!
  title: String!
  author: String!
}

3. 实现解析函数

你需要为 schema 中定义的每一个字段编写解析函数,这些函数定义了如何获取或修改数据。

:RESTful API 中,每个端点的处理函数通常直接操作数据库或调用服务层的代码

app.get("/api/books/:id", (req, res) => {
  const { id } = req.params;
  // 从数据库中找到书籍并返回
});

:GraphQL 中,你编写解析函数来获取数据

const root = {
  book: ({ id }) => {
    // 使用 id 从数据库中找到书籍并返回
  },
  createBook: ({ title, author }) => {
    // 创建新书籍并返回
  },
  // ...更多解析函数
};

4. 调整前后端交互

在 GraphQL 中,前端不再需要知道许多不同的端点,而是通过构造查询和变更来获取所需的数据。

:RESTful API 调用示例(使用 fetch)

fetch("/api/books/1")
  .then((response) => response.json())
  .then((book) => console.log(book));

:GraphQL 调用示例(使用 fetch)

fetch("/graphql", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    query: `
      {
        book(id: "1") {
          title
          author
        }
      }
    `,
  }),
})
  .then((response) => response.json())
  .then((data) => console.log(data.data.book));

引入 GraphQL 后,后端需进行以下主要改动:

  • 配置 GraphQL 服务端点。
  • 定义 GraphQL schema,包括类型定义和操作。
  • 实现对应的解析函数(resolvers),用于获取和修改数据。
  • 适配现有数据源和服务层,以支持新的解析函数。
  • 更新前后端交互方式,前端使用 GraphQL 查询和变更代替 REST API 调用。

6. 是否接入 GraphQL 的判断标准

判断项目是否需要接入 GraphQL 主要取决于项目的现有需求、未来的发展以及潜在的收益是否超过了接入成本。以下是一些评估是否需要接入 GraphQL 的考量因素:

现有 API 的局限性

  • 数据获取问题:如果客户端经常面临过度获取或获取不足的问题,导致不必要的网络流量或多次往返请求,则 GraphQL 可以通过允许客户端精确指定所需数据来解决这些问题。
  • 复杂的数据交互:如果你的应用需要处理复杂的数据交互,或者有多个数据模型之间有复杂的关联,GraphQL 的查询合并能力可以简化客户端的请求逻辑。

前后端开发流程

  • 频繁的前后端协调:如果前端团队经常需要后端团队为新的界面或组件调整 API,引入 GraphQL 可以让前端独立于后端更灵活地获取数据。
  • API 版本管理挑战:如果项目中存在多个版本的 API,并且难以统一和维护,GraphQL 可以提供更灵活的数据交互而无需维护多个 API 版本。

性能和优化需求

  • 移动应用或带宽优化:对于移动或低带宽环境,GraphQL 的按需数据查询可减少不必要的数据传输,从而优化性能和用户体验。

技术生态和团队技能

  • 团队技能和资源:考虑团队是否有能力学习和实现 GraphQL,以及是否有足够的资源来支持迁移过程。
  • 社区支持和生态系统:考察 GraphQL 的社区支持程度以及是否有适合项目需求的库和工具。

成本与收益分析

  • 长期收益:思考 GraphQL 是否能带来长期的收益,例如提升开发效率、减少错误和提升性能。
  • 迁移成本:评估接入 GraphQL 的直接和间接成本,包括开发、测试、部署和维护。

策略和风险

  • 逐步迁移的可行性:评估是否可以逐步引入 GraphQL,而不是一次性重构整个后端服务。

使用场景

  • 公共 API:如果你的项目是面向广大开发者的公共 API,那么提供 GraphQL 接口可以增加其灵活性和吸引力。
  • 多客户端应用:如果你的服务需要支持多种类型的客户端(如 Web、移动、桌面等),GraphQL 可以通过一个统一的接口满足不同客户端的数据需求。

最终是否接入 GraphQL 取决于对以上因素的评估以及对业务优先级的考量。如果经过分析,你认为现有的 REST API 已经足够好,且引入 GraphQL 的成本超出了预期收益,那么可能没有必要立即进行迁移。但如果 GraphQL 带来的好处明显,可以显著提升应用的数据交互效率和开发体验,那么接入 GraphQL 可能是一个值得的投资。在任何情况下,建议先进行小规模的试点项目来评估 GraphQL 在实际环境中的效果。

7. 高并发场景注意事项

在高并发场景下处理 GraphQL 请求需要考虑几个关键因素,以确保应用程序的性能和稳定性。以下是一些处理方法和最佳实践:

1. 查询优化

  • 查询分析和限制:使用查询分析工具来防止复杂度过高的查询,限制查询的深度和大小,避免因为过于复杂的查询导致性能问题。
  • 查询白名单:预定义允许的查询列表,避免不需要或恶意的查询对服务器造成负担。

2. 性能优化

  • 数据加载器 (Data Loader):使用数据加载器(如 Facebook 的 DataLoader)来批处理和缓存后端数据请求,减少数据库访问次数,防止 N+1 查询问题。
  • 持久化查询:将常见的查询结果持久化或缓存起来,以便更快地返回数据,减少对数据库和计算资源的请求。

3. 服务器优化

  • 服务器扩展:在必要时扩展服务器实例,可以是水平扩展(增加更多服务器)或垂直扩展(增加单个服务器的资源)。
  • 负载均衡:使用负载均衡器来分配请求到不同的服务器实例。
  • 异步和非阻塞操作:使用异步 IO 和非阻塞操作来改善性能和资源利用率。

4. 缓存策略

  • 应用级缓存:在应用层面实现对象缓存,如使用 Redis 或 Memcached 来缓存常用数据。
  • CDN 缓存:使用内容分发网络(CDN)缓存静态内容和公共查询。

5. 模块化和微服务

  • 模块化 schema:将 GraphQL schema 组织成模块,有助于分离关注点,提升维护性。
  • 微服务架构:在复杂系统中,考虑使用微服务架构,可以独立扩展和维护不同的业务逻辑。

6. 监控和日志

  • 性能监控:实现性能监控,记录响应时间和系统资源使用情况,以便快速发现性能瓶颈。
  • 日志记录:记录详细的日志信息,以便在出现问题时进行调试和优化。

7. 安全性和控制

  • 速率限制:实施速率限制和请求节流来控制每个用户或 IP 地址的请求数量。
  • 身份验证和授权:确保所有请求都通过必要的身份验证和授权检查,防止未授权的访问和资源滥用。

8. 错误处理和冗余

  • 错误处理:优化错误处理逻辑,防止异常导致的服务中断。
  • 服务冗余:设置服务冗余,如数据库和服务器的冗余副本,确保服务的高可用性。

在高并发场景下处理 GraphQL 请求需要综合考虑查询优化、服务器性能、缓存、监控和安全等多个方面。通常需要根据实际场景和业务需求来定制解决方案,并通过持续的监控和优化来维护系统的健康状态。此外,也可以考虑使用云服务和 Serverless 架构来动态调整资源,应对高并发带来的挑战。

8. GraphQL 生态

在这里插入图片描述

GraphQL 的生态系统是由许多工具、库、平台和社区支持的资源组成的。这个生态系统可以帮助开发者在不同的阶段和不同的层面上使用 GraphQL,包括创建、运行、测试和集成 GraphQL API。以下是 GraphQL 生态系统的一些主要类别和资源:

查询语言和运行时

  • GraphQL.js:Facebook 官方的 JavaScript GraphQL 实现。
  • GraphQL-Java:用于 Java 的 GraphQL 库。
  • graphql-ruby:Ruby 实现的 GraphQL 库。
  • Graphene:用于 Python 的 GraphQL 框架,有 Django 集成版本 Graphene-Django。

客户端库

  • Apollo Client:功能丰富的 GraphQL 客户端,用于管理数据和缓存,支持多个前端框架。
  • Relay:为 React 应用构建的 GraphQL 客户端,专注于性能和紧密集成。
  • urql:一个简单且可扩展的 GraphQL 客户端,支持 React 和其他 JavaScript 库。

服务端库和工具

  • Apollo Server:一个用于构建 GraphQL 服务器的开源库,与 Express、Koa、Hapi 等多个 Node.js 服务器框架兼容。
  • GraphQL Yoga:基于 Express 的轻量级 GraphQL 服务器,易于设置。
  • Express-GraphQL:将 GraphQL API 集成到 Express 应用中的库。
  • Hasura:即时的 GraphQL API 生成器,可以直接连接到你的数据库并自动创建 GraphQL API。

UI 开发工具

  • GraphiQL:一个交互式的 Web IDE,用于在浏览器中测试 GraphQL 查询。
  • GraphQL Playground:一个功能丰富的 GraphQL IDE,类似于 GraphiQL,但包含更多功能,如支持多个环境、交互式文档等。

代码生成器

  • GraphQL Code Generator:一个工具,它可以从你的 GraphQL schema 和操作生成前端和后端的代码。
  • Apollo Tooling:用于开发 GraphQL 的工具集,包括代码生成、类型生成等。

中间件和集成

  • graphql-middleware:一个允许开发者为 GraphQL 服务器添加中间件的库。
  • Prisma:将数据库转换为 GraphQL API 的工具,提供 ORM 支持。

测试工具

  • EasyGraphQL Tester:用于测试 GraphQL API 的 JavaScript 库。
  • Apollo Server Testing:Apollo Server 的测试工具,使得集成测试更加容易。

监控和性能

  • Apollo Studio (以前的 Apollo Engine):用于监控和优化 GraphQL API 性能的工具。
  • GraphQL Network Inspector:Chrome 扩展程序,用于监控 GraphQL 网络请求。

社区和学习资源

  • GraphQL.org:官方 GraphQL 网站,包括文档、教程和社区资源。
  • How to GraphQL:一个全面的学习平台,提供 GraphQL 的教程和课程。

安全工具

  • graphql-shield:用于 GraphQL 服务器的权限系统,允许创建基于规则的访问控制。

数据库和持久化

  • Postgraphile:可以快速将 PostgreSQL 数据库转变成一个强大的 GraphQL API 服务器。
  • FaunaDB:提供图形支持的数据库,与 GraphQL 无缝集成。

GraphQL 生态系统不断发展,不断有新的工具和库被创建出来,以支持 GraphQL 在更多场景和平台上的应用。开发者可以根据项目的需求和团队的偏好,选择合适的工具来构建和维护 GraphQL API。

9. 旧项目改造建议

将一个原有的旧项目改造成 GraphQL 的确可能是一项复杂的任务,这取决于项目的规模、现存的 API 设计、后端架构以及你希望从 GraphQL 中获得的好处。以下是一些建议和考虑因素,帮助你评估和简化改造过程:

简化改造的方法:

  1. 逐步迁移:不需要一步到位地完成所有改造。你可以逐步迁移,例如,先为一小部分功能引入 GraphQL。同时保留 REST API 和 GraphQL,然后逐步扩大 GraphQL 的应用范围。

  2. 使用桥接层:在 REST API 之上构建一个 GraphQL 层,这个层作为翻译器,将 GraphQL 查询转换为对底层 REST API 的调用。这可以使得你在不触碰现存业务逻辑的情况下利用 GraphQL。

  3. 工具和库:使用现有的工具和库,如 Apollo Server,它可以帮你快速地搭建一个 GraphQL 服务,并集成到现有的 Node.js 应用程序中。

  4. 自动生成 Schema:考虑使用工具自动生成 GraphQL schema,特别是如果你的数据库模式非常稳定的话。例如,PostgraphilePrisma 可以从现有的 PostgreSQL 数据库生成完整的 GraphQL API。

  5. 模块化:将 GraphQL schema 分解成多个模块,逐模块实施迁移。可以分类型,也可以按业务域来分。

判断是否应该进行改造:

  1. 客户端需求:如果你的前端团队经常因为数据过多或过少而不得不进行多余的网络请求,或者需要更灵活地获取数据,那么 GraphQL 可能是一个合适的选择。

  2. API 版本管理:如果你在管理多个版本的 API,并且想简化这个流程,GraphQL 由于其灵活性,可能是一个更好的解决方案。

  3. 性能考虑:如果应用的性能受限于数据传输,例如移动应用或网络条件不佳的环境,GraphQL 的精确数据获取能力可以帮助优化性能。

  4. 前后端分离:如果你的项目是前后端分离的架构,并且希望前端有更大的自主性来决定数据需求,那么迁移到 GraphQL 可以减少前后端之间的依赖。

风险和挑战:

  1. 学习曲线:GraphQL 有自己的查询语言和概念,团队成员可能需要一些时间来学习和适应。

  2. 重构成本:重构可能会引入 bug 和性能问题,需要投入时间和资源来保证平稳过渡。

  3. 现有架构的兼容性:改造可能需要对现有的数据访问层进行大量修改,以适配 GraphQL 的解析器和类型系统。

  4. 监控和安全:引入 GraphQL 之后,需要考虑新的监控和安全策略,因为所有请求都通过单一端点进入,可能会有不同的安全挑战。

综合来看,是否对旧项目进行改造需要平衡项目需求、预期好处与可能的成本。如果决定迁移到 GraphQL,采取逐步迁移的策略通常更为稳妥,可以降低风险并逐步评估新技术的影响。

10. 简单示例

下面我将提供一些基本的 GraphQL 代码示例,包括定义一个简单的 GraphQL schema、编写查询(Query)、变更(Mutation)以及在 Node.js 环境中设置一个简单的 GraphQL 服务器。

定义 GraphQL Schema

在 GraphQL 中,你需要定义一个类型系统(schema),在这个 schema 中指定你的数据模型和可用的查询和变更操作。以下是一个简单的 schema 示例:

type Query {
  book(id: ID!): Book
  author(name: String!): Author
}

type Mutation {
  addBook(title: String!, author: String!): Book
}

type Book {
  id: ID!
  title: String!
  author: Author!
}

type Author {
  id: ID!
  name: String!
  books: [Book!]
}

编写查询 (Query)

一旦你有了 schema,你就可以通过编写查询来获取数据。以下是一些查询示例:

# 获取 ID 为 1 的书籍信息
query {
  book(id: "1") {
    id
    title
    author {
      name
    }
  }
}

# 获取名为 "J.K. Rowling" 的作者信息
query {
  author(name: "J.K. Rowling") {
    id
    name
    books {
      title
    }
  }
}

编写变更 (Mutation)

如果你想修改数据,你可以通过编写变更来实现。以下是一个变更示例:

# 添加一本新书
mutation {
  addBook(
    title: "Harry Potter and the Sorcerer's Stone"
    author: "J.K. Rowling"
  ) {
    id
    title
  }
}

在 Node.js 中设置 GraphQL 服务器

你可以使用 expressexpress-graphql 快速设置一个 GraphQL 服务器。首先,安装必要的 npm 包:

npm install express express-graphql graphql

然后可以编写如下代码来启动服务器:

const express = require("express");
const { graphqlHTTP } = require("express-graphql");
const { buildSchema } = require("graphql");

// 使用 GraphQL schema 语言构建一个 schema
const schema = buildSchema(`
  type Query {
    hello: String
  }
`);

// 根提供者提供 API 的每个端点的解析器函数
const root = {
  hello: () => "Hello, world!",
};

const app = express();
app.use(
  "/graphql",
  graphqlHTTP({
    schema: schema,
    rootValue: root,
    graphiql: true, // 开启 GraphiQL 工具进行测试
  })
);

app.listen(4000, () => {
  console.log("Running a GraphQL API server at http://localhost:4000/graphql");
});

运行上述代码后,你可以在浏览器中访问 http://localhost:4000/graphql 并使用 GraphiQL 工具来发送查询和变更请求。

这些示例保持简单明了的目的,并且没有涉及错误处理、认证、高级的 schema 设计或数据持久化等方面的内容。在实际项目中,GraphQL 服务端的实现会更为复杂。


在这里插入图片描述

github原文地址

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java以SSL方式连ES

先做准备工作,浏览器方式访问 ES7.X url https://127.0.0.1:8027 弹出用户名和密码 输入后在浏览器得到 { “name” : “DTCNPEMS04”, “cluster_name” : “cnp-es-cluster”, “cluster_uuid” : “wb0So_FqQBOKqtXnsqofTg”, “version” : { “number” : “7.…

力扣hot100 两数相加 链表 思维

Problem: 2. 两数相加 Code ⏰ 时间复杂度: O ( n ) O(n) O(n) 🌎 空间复杂度: O ( n ) O(n) O(n) /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.…

prometheus监控RabbitMQ策略

一般用官方的rabbitmq_exporter采取数据即可,然后在普米配置。但如果rabbitmq节点的队列数超过了5000,往往rabbitmq_exporter就会瘫痪,因为rabbitmq_exporter采集的信息太多,尤其是那些队列的细节,所以队列多了&#x…

android camera的使用以及输出的图像格式

一、Camera 1.1、结合SurfaceView实现预览 1.1.1、布局 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-au…

SpringBoot项目多数据源配置与MyBatis拦截器生效问题解析

在日常项目开发中&#xff0c;由于某些原因&#xff0c;一个服务的数据源可能来自不同的库&#xff0c;比如&#xff1a; 对接提供的中间库&#xff0c;需要查询需要的数据同步数据&#xff0c;需要将一个库的数据同步到另一个库&#xff0c;做为同步工具的服务对接第三方系统…

离零售业智能体时代的真正开启还有多远?

AIGC&#xff08;生成式人工智能&#xff09;当道的2023年&#xff0c;将LLM&#xff08;大语言模型&#xff09;的各类生成式能力发挥到淋漓尽致、精彩纷呈的程度。各行各业一边在观望大语言模型不断扩宽的商业运用可能&#xff0c;一边在继续探寻能够不断拓宽企业往纵深发展的…

C/C++ - Auto Reference

目录 auto Reference auto 当使用auto​​关键字声明变量时&#xff0c;C编译器会根据变量的初始化表达式推断出变量的类型。 自动类型推断&#xff1a;auto​​关键字用于自动推断变量的类型&#xff0c;使得变量的类型可以根据初始化表达式进行推导。 初始化表达式&#x…

Redis的五种常用数据类型详解及相关面试问题

目录 Redis的五种常用数据类型详解 简述 Redis五种基本数据类型 String字符串 常用命令 应用场景 Hash散列表 常用命令 使用场景 List链表 常用命令 应用场景 Set( 集合) 常用命令 应用场景 SortedSet( 有序集合) zset 常用命令介绍 应用场景 面试题常问的数…

【驱动】TI AM437x(内核调试-07):devmem2直接读写内存、寄存器,devkmem读取内核变量

1、/dev/mem 和 /dev/kmem 1)/dev/mem: 物理内存的全镜像。可以用来访问物理内存 2)/dev/kmem: kernel看到的虚拟内存的全镜像。可以用来访问kernel的内容。kernel部分内存用户空间本不可访问。但是因为所有进程共享内核空间的页表。所以内核虚拟地址对应物理地址是确定的…

【码农新闻】 CSS 即将支持嵌套,SASS/LESS 等预处理器已无用武之地?常见的Web攻击手段,拿捏了!......

目录 【码农新闻】 CSS 即将支持嵌套&#xff0c;SASS/LESS 等预处理器已无用武之地&#xff1f;常见的Web攻击手段&#xff0c;拿捏了&#xff01;...... 流行框架与库的源码分析与最简实现CSS 即将支持嵌套&#xff0c;SASS/LESS 等预处理器已无用武之地&#xff1f;常见的W…

低代码开发平台与可组合业务:实现高效应用的完美结合

如今&#xff0c;有很多产品已经走在了模块化的道路上&#xff0c;例如一款吸尘器&#xff0c;它可以经由不同配件组合来实现不同的功能&#xff0c;来满足消费者的需求。这种类似于“一站式”的产品解决方案&#xff0c;正在成为一种可见的趋势。 今年年初&#xff0c;Gartne…

函数递归知识点与经典例题

目录 递归的概念 &#xff08;什么是递归&#xff09; 递归举例 举例1&#xff1a;求n的阶乘 举例2&#xff1a;顺序打印一个整数的每一位 递归与迭代 举例3&#xff1a;求第n个斐波那契数 递归的概念 &#xff08;什么是递归&#xff09; 递归是学习C语言函数绕不开的⼀…

第13章_泛型(集合中使用泛型,比较器中使用泛型,自定义泛型结构,泛型在继承上的体现,通配符的使用)

文章目录 第13章_泛型(Generic)本章专题与脉络1. 泛型概述1.1 生活中的例子1.2 泛型的引入 2. 使用泛型举例2.1 集合中使用泛型2.1.1 举例2.1.2 练习 2.2 比较器中使用泛型2.2.1 举例2.2.2 练习 2.3 相关使用说明 3. 自定义泛型结构3.1 泛型的基础说明3.2 自定义泛型类或泛型接…

一文学习Thrift RPC

Thrift RPC引言 Thrift RPC的特点 Thrift 是一个RPC的框架&#xff0c;和Hessian RPC有什么区别&#xff0c;最重要的区别是Thrift可以做异构系统开发。 什么是异构系统&#xff0c;服务的提供者和服务的调用者是用不同语言开发的。 为什么会当前系统会有异构系统的调用&…

Flume介绍

一、介绍 Apache Flume 是一种分布式、可靠且可用的系统&#xff0c;用于有效地收集、汇总大量日志数据&#xff0c;并将其从多个不同来源转移到集中式数据存储区。 Apache Flume 的使用不仅限于日志数据聚合。由于数据源是可定制的&#xff0c;Flume 可用于传输大量事件数据&a…

C++学习| QT快速入门

QT简单入门 QT Creater创建QT项目选择项目类型——不同项目类型的区别输入项目名字和路径选择合适的构建系统——不同构建系统的却别选择合适的类——QT基本类之间的关系Translation File选择构建套件——MinGW和MSVC的区别 简单案例&#xff1a;加法器设计界面——构建加法器界…

红帽认证有啥用?初级红帽认证证书值得考吗?

大家好&#xff0c;这里是G-LAB IT实验室。 今天我们来了解一下Linux红帽认证。 红帽认证已成为企业和个人竞相追逐的热门资质。 红帽认证认可度究竟如何?红帽RHCSA认证含金量又有多高? 下面G-LAB将为你一一解答。 1 、红帽认证认可度怎么样&#xff1f; 事实上&#xff0…

git:git reset 和 git revert

在使用 git 进行项目开发的过程中&#xff0c;有时会出现错误提交的情况&#xff0c;这时就需要能够撤销错误的提交&#xff0c;将代码恢复到提交之前的样子。根据不同情况&#xff0c;可以使用 git reset 或 git revert 命令。 一. git reset git reset 的原理是修改 HEAD 的…

php怎么输入一个变量,http常用的两种请求方式getpost(ctf基础)

php是网页脚本语言&#xff0c;网页一般支持两种提交变量的方式&#xff0c;即get和post get方式传参 直接在网页URL的后面写上【?a1027】&#xff0c;如果有多个参数则用&符号连接&#xff0c; 如【?a10&b27】 post方式传参 需要借助插件&#xff0c;ctfer必备插…

羊奶与牛奶,谁更好?

羊奶与牛奶&#xff0c;谁更好&#xff1f; 羊奶和牛奶是我们日常饮食中常见的乳制品&#xff0c;但究竟哪种更好呢&#xff1f;今天就让小编羊大师带大家一起来探讨一下&#xff0c;看看羊奶和牛奶在各方面的优势和劣势&#xff0c;帮助你作出更明智的选择。 让我们从营养价…