Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Redis

Khởi chạy Ứng dụng Nuxt 3 với Redis Serverless để Tăng Hiệu suất Nhanh chóng

Giới thiệu

Nếu bạn từng phải xây dựng một ứng dụng theo dõi việc sử dụng, hạn chế tài nguyên hoặc lấy dữ liệu từ cache để tăng hiệu suất ứng dụng, thì bạn sẽ biết Redis là câu trả lời cho các yêu cầu này! Redis là cơ sở dữ liệu key-value trong bộ nhớ (in-memory). Nó là mã nguồn mở và là viết tắt của Remote Dictionary Server.

Trong bài viết này, chúng ta sẽ thảo luận về Upstash, cơ sở dữ liệu Redis và bản phát hành beta gần đây của framework Vue SSR, Nuxt 3. Đây là một bài viết thân thiện với người mới bắt đầu khám phá cơ sở dữ liệu Redis, nơi chúng ta sẽ xây dựng một ứng dụng cơ bản theo dõi lượt truy cập trang của ứng dụng Nuxt.

Tài nguyên

Upstash là gì?

Upstash là một dịch vụ cung cấp truy cập serverless vào cơ sở dữ liệu Redis. Đó là lý do tại sao việc học các kiến thức cơ bản của Redis bao gồm các trường hợp sử dụng và các lệnh có sẵn để thao tác với các loại dữ liệu khác nhau trở nên thiết yếu.

Redis là gì?

Redis có các trường hợp sử dụng phổ biến như:

  • Cache dữ liệu và phiên (session)
  • Bảng xếp hạng (Leaderboards) - xếp hạng tên và điểm số trong game hoặc phần mềm được xây dựng theo nguyên tắc game hóa
  • Hàng đợi (Queues) - lên lịch các tác vụ để xử lý sau trong nền
  • Đo lường/số lượng sử dụng (Usage metering/counting) - hạn chế việc sử dụng tài nguyên, kiểm soát phân phối tài nguyên hoặc chỉ đếm ở quy mô lớn để theo dõi và phân tích việc sử dụng, như các trang thương mại điện tử, mạng xã hội, ứng dụng di động, v.v.
  • Lọc nội dung (Content filtering) - ví dụ, lọc nội dung dựa trên danh sách từ bị cấm

Ở mức độ cơ bản, cơ sở dữ liệu Redis lưu trữ dữ liệu theo cặp key-value. Nhưng nó cũng có thể lưu trữ dữ liệu trong các cấu trúc dữ liệu nâng cao như Danh sách (Lists), Tập hợp (Sets), Tập hợp đã sắp xếp (Sorted sets), v.v. Redis cũng cung cấp tập hợp các lệnh để thao tác các cấu trúc dữ liệu này. Vì chúng ta sẽ sử dụng một trong số chúng trong ứng dụng ví dụ, nên đáng để xem xét định nghĩa cấp cao của chúng.

  • Lists (Danh sách) - giống như một mảng cơ bản. List cho phép bạn đẩy (push) và lấy (pop) các mục từ cả hai đầu của một chuỗi, lấy các mục riêng lẻ và thực hiện nhiều hoạt động khác. Các lệnh List có tiền tố chữ L, ví dụ: LPOP, LPUSH, LSET, v.v.
  • Hash - cho phép bạn lưu trữ các nhóm cặp key-value trong một khóa Redis duy nhất. Các lệnh Hash có tiền tố chữ H, ví dụ: HSET, HGET, HDEL, v.v.
  • Sets (Tập hợp) - giống như lists, nhưng Sets là duy nhất và lưu trữ các mục trong danh sách không có thứ tự. Đó là lý do Sets không thể sắp xếp, nhưng bạn có thể nhanh chóng thêm, xóa và xác định xem một mục có trong Set hay không. Các lệnh Set có tiền tố chữ S, ví dụ: SADD, SCARD, SISMEMBER, v.v.
  • Sorted sets (Tập hợp đã sắp xếp) - giống như sets, nhưng Sorted sets cho phép sắp xếp theo điểm số (scores) trông rất giống cặp key-value. Chúng ta cũng có thể thao tác và sắp xếp các điểm số số này. Các lệnh Sorted set có tiền tố chữ Z, ví dụ: ZADD, ZINCRBY, ZSCORE, v.v.

Bạn có thể tìm hiểu thêm về các lệnh Redis khác tại https://redis.io/commands

Thiết lập Upstash

Làm theo hướng dẫn để thiết lập tài khoản và cơ sở dữ liệu theo tài liệu tại https://docs.upstash.com/

Trước khi bắt đầu tạo ứng dụng Nuxt, hãy đảm bảo tài khoản Upstash của bạn đã sẵn sàng. Bạn nên có thể tạo một cơ sở dữ liệu với gói miễn phí.

Khi cơ sở dữ liệu của bạn được tạo, bạn có thể tạo và truy cập cơ sở dữ liệu Redis bằng bất kỳ Redis client nào. Ngoài ra, bạn có thể sử dụng CLI dựa trên trình duyệt 👇 được cung cấp trong bảng điều khiển Upstash để bắt đầu ngay lập tức.

Khởi chạy Ứng dụng Nuxt 3 với Redis Serverless để Tăng Hiệu suất Nhanh chóng

CLI dựa trên trình duyệt được cung cấp trong bảng điều khiển Upstash

Redis-cli

Bạn có thể thiết lập redis-cli trên terminal máy tính của mình để tạo và truy cập cơ sở dữ liệu Redis trực tiếp từ giao diện dòng lệnh của mình.

Các gói npm Redis

Chúng ta cũng có một số gói npm để tương tác với cơ sở dữ liệu Redis. Chúng ta sẽ sử dụng 1) @upstash/redis và 2) ioredis - để truy cập các lệnh Redis trong dự án Nuxt của chúng ta.

Trong phần tiếp theo, chúng ta sẽ thiết lập dự án Nuxt. Nuxt là một framework SSR được xây dựng trên nền tảng Vue. Nuxt Labs vừa công bố bản phát hành beta Nuxt 3. Vậy hãy thiết lập một dự án Nuxt 3 mới.

Nuxt 3 hiện đang ở phiên bản beta, hãy lưu ý rằng nó chưa sẵn sàng cho production.

⚡Hãy nói về Nuxt 3

Nuxt 3 giới thiệu một CLI hoàn toàn mới gọi là nuxi để tạo ứng dụng Nuxt.

npx nuxi init nuxt3-app

Chúng ta sẽ tạo thư mục /pages và thêm một vài route đơn giản như bên dưới 👇

-pages
--index.vue
--about.vue
app.vue

app.vue là một khái niệm mới trong Nuxt 3 đóng vai trò là component chính. app.vue sẽ được tải cho mọi route được định nghĩa trong thư mục /pages.

Nitro server engine ⚙️

Nuxt 3 cũng giới thiệu một server engine hoàn toàn mới gọi là Nitro. Chúng ta có thể tận dụng sức mạnh của Nitro để tạo các endpoint API phía server và middleware phía server bằng cách đơn giản tạo thư mục server với api và middleware làm thư mục con. Bạn có thể xem cấu trúc thư mục tối giản này trong repo GitHub.

-server
--api
--middleware

Cả API và middleware đều nên xuất ra một hàm mặc định xử lý các yêu cầu API và trả về promise/dữ liệu JSON. Khác với Nuxt 2, chúng ta không phải định nghĩa server-middleware trong nuxt.config.js.

Dưới đây là danh sách các bước cấp cao chúng ta cần thực hiện để xây dựng ứng dụng:

  • Đầu tiên, kết nối với cơ sở dữ liệu Redis.
  • Để ghi nhận lượt truy cập trang, chúng ta chặn mọi yêu cầu trang được gửi đến server, tăng bộ đếm của trang đó lên một và lưu giá trị vào cơ sở dữ liệu Redis.
  • Sau đó, chúng ta thực hiện cuộc gọi API từ phía client để lấy số lượt truy cập từ cơ sở dữ liệu Redis và hiển thị nó trên trang Nuxt.

Về mặt khái niệm, sơ đồ dưới đây cho thấy những gì chúng ta đang cố gắng xây dựng 👇

Khởi chạy Ứng dụng Nuxt 3 với Redis Serverless để Tăng Hiệu suất Nhanh chóng

Tìm hiểu thêm về Nuxt 3 tại https://v3.nuxtjs.org/getting-started/installation

Sử dụng Redis Client REST

Upstash cung cấp Redis client dựa trên HTTP/REST riêng của mình - @upstash/redis - mà chúng ta có thể thêm làm dependency trong dự án Nuxt.

yarn add @upstash/redis

Xác thực Cơ sở dữ liệu Redis

Để xác thực cơ sở dữ liệu Redis, chúng ta cần xác định các biến môi trường sau:

  • URL REST (UPSTASH_REDIS_REST_URL), và
  • Token (UPSTASH_REDIS_REST_TOKEN)

...từ bảng điều khiển Upstash - trong phần cơ sở dữ liệu.

Cấu hình Runtime riêng tư

Bây giờ, để lộ ra các biến môi trường này ở phía server, Nuxt cung cấp cấu hình runtime mà chúng ta định nghĩa trong file nuxt.config.js.

// nuxt.config.js
export default defineNuxtConfig({
  publicRuntimeConfig: {},
  privateRunimeConfig: {
    UPSTASH_REDIS_REST_URL: process.env.UPSTASH_REDIS_REST_URL,
    UPSTASH_REDIS_REST_TOKEN: process.env.UPSTASH_REDIS_REST_TOKEN,
  },
});

Tiếp theo, chúng ta có thể truy cập trực tiếp các biến môi trường này bằng cách import #config.

import { Redis } from "@upstash/redis";
import config from "#config";

const redis = new Redis({
  url: config.UPSTASH_REDIS_REST_URL,
  token: config.UPSTASH_REDIS_REST_TOKEN,
});

Là một phương án thay thế, phương pháp zero-config (không cấu hình) là thêm UPSTASH_REDIS_REST_URL và UPSTASH_REDIS_REST_TOKEN trực tiếp vào file .env và tạo instance redis const redis = Redis.fromEnv() mà không cần truyền các biến này cho Redis. Lưu ý rằng phép màu này chỉ áp dụng khi sử dụng Redis client @upstash/redis.

Chặn yêu cầu với Nuxt server-middleware

Chúng ta tự do sử dụng bất kỳ lệnh Redis nào cần thiết từ đây. Cho ví dụ này, chúng ta sẽ sử dụng sorted-set (tập hợp đã sắp xếp), vì sorted-sets là duy nhất và cũng cho phép sắp xếp và thao tác SCORE.

Ví dụ, chúng ta có thể sử dụng zincrby để tăng SCORE của trang mỗi khi có yêu cầu được gửi đến trang.

// server/middleware/pageCount.js
import { Redis } from "@upstash/redis";
import { getRedisKey } from "../utils";

const redis = Redis.fromEnv();

export default async function (req, res, next) {
  const redisKey = getRedisKey(req.url);
  await redis.zincrby("myPageCounts", 1, redisKey);
  next();
}

Tạo namespace

Redis là cơ sở dữ liệu NoSQL lưu trữ dữ liệu theo cặp key-value. Nó không có khái niệm khóa tự động tăng hoặc bất kỳ cách động nào để tạo UUID duy nhất bất kỳ loại nào. Đây là nơi chúng ta giới thiệu hàm tiện ích getRedisKey().

Hàm tiện ích này xử lý URL yêu cầu và tạo khóa duy nhất - mà chúng ta sẽ sử dụng để lưu trữ lượt truy cập cho từng trang. Cách này giúp chúng ta ngăn chặn việc tăng bộ đếm dựa trên cùng một khóa.

Trong ví dụ của chúng ta, chúng ta lấy URL yêu cầu và thay thế tất cả các trường hợp của '/' bằng '.' để tạo khóa được đặt tên duy nhất (namespaced keys).

export const getRedisKey = (url: string) => {
  const reqURL = url?.replace("/", ".");
  const redisKey = reqURL === "." ? "page.home" : `page${reqURL}`;
  return redisKey;
};

Điều này sẽ giúp chúng ta chuyển đổi, ví dụ: trang /about thành một khóa được đặt tên sẽ đọc là page.about

Truy cập Cơ sở dữ liệu Redis bằng REST API Endpoints

Hãy tạo một endpoint API sẽ lấy số lượng hiện tại hoặc SCORE cho các trang tương ứng.

Trong Nuxt 3, có hai cách để lấy dữ liệu. 1) useAsyncData và 2) useFetch. Trong app.vue, chúng ta sẽ sử dụng useAsyncData cùng với $fetch được cung cấp bởi thư viện ohmyfetch.

// app.vue

Như bạn thấy, cùng với cuộc gọi API, chúng ta đã truyền đường dẫn router làm tham số truy vấn để xác định trang đang được truy cập 👇

$fetch("/api/count", {
  params: {
    path: router.path
  }
});

Khác với server-middleware, chúng ta sẽ phải sử dụng endpoint API này, /api/count để lấy số lượt truy cập. Đó là phần thú vị! 👇

Hãy tạo endpoint API này tại server/api/count.ts. Chúng ta sẽ sử dụng phương thức useQuery do thư viện h3 cung cấp để truy cập tham số truy vấn được gửi từ phía client.

// server/api/count.ts
import { useQuery } from "h3";

export default async (req, res) => {
  let query = await useQuery(req);
  const redisKey = getRedisKey(query.path);
};

Ở đây 👆 chúng ta sẽ sử dụng cùng tiện ích getRedisKey() để đảm bảo khóa này khớp với khóa được đặt tên chúng ta đã dùng trong middleware để tăng số lượt truy cập của trang.

Vậy bây giờ chúng ta có thể truyền khóa này vào zscore mà chúng ta chắc chắn nó tồn tại trong cơ sở dữ liệu để lấy SCORE/số lượng. 👇

// server/api/count.ts
// ...
import { Redis } from "@upstash/redis";

const redis = Redis.fromEnv();

export default async () => {
  // ...
  const count = await redis.zscore("myPageCounts", redisKey);
  return { count };
};

Sử dụng API Redis trực tiếp với ioredis

Chúng ta có thể đạt được cùng kết quả bằng thư viện ioredis.

yarn add ioredis

Khi sử dụng ioredis, chúng ta sẽ không có phương thức auth sẵn có. Tuy nhiên, chúng ta có chuỗi kết nối - có sẵn trong bảng điều khiển Upstash - mà chúng ta có thể dùng để kết nối với cơ sở dữ liệu Redis.

Chúng ta có thể đặt UPSTASH_REDIS_CONN làm biến cấu hình runtime tương tự như chúng ta đã làm trước đó cho rest-url và token.

// nuxt.config.js
export default defineNuxtConfig({
  publicRuntimeConfig: {},
  privateRunimeConfig: {
    UPSTASH_REDIS_CONN: process.env.UPSTASH_REDIS_CONN,
  },
});

Tiếp theo, trong middleware, chúng ta sẽ tạo instance new Redis() để tạo kết nối và truy cập tất cả các lệnh Redis từ client 👇

// server/middleware/pageCount.js
import config from "#config";
import Redis from "ioredis";

const client = new Redis(config.UPSTASH_REDIS_CONN);

Chặn yêu cầu với Nuxt server-middleware

Middleware Nuxt của chúng ta sẽ giữ nguyên như trước, ngoại trừ cách chúng ta truy cập zincrby sẽ thay đổi 👇

// server/middleware/pageCount.js
// ...
export default async function (req, res, next) {
  // ...
  await client.zincrby("myPageCounts", 1, redisKey);
  next();
}

Truy cập Cơ sở dữ liệu Redis bằng REST API Endpoints

Trước đó, chúng ta tạo endpoint API tùy chỉnh server/api/count.ts để lấy số lượng. Endpoint API đó cũng sẽ giữ nguyên, ngoại trừ cách chúng ta gọi phương thức zscore sẽ thay đổi một chút 👇

// server/api/count.ts
import config from "#config";
import Redis from "ioredis";

const client = new Redis(config.UPSTASH_REDIS_CONN);

export default async (req: IncomingMessage, res: ServerResponse) => {
  // ...
  const count = await client.zscore("myPageCounts", redisKey);
  return { count };
};

Kiểm tra với Upstash CLI

Vì chúng ta đang lưu trữ tất cả dữ liệu vào sorted-set, chúng ta có thể sử dụng zrange để lấy tất cả các mục từ sorted-set của chúng ta.

Bạn có thể truy cập Redis CLI được cung cấp trong bảng điều khiển Upstash và chạy lệnh sau:

zrange myPageCounts 0 -1

Ở đây 👆:

  • myPageCounts là tên sorted-set của chúng ta,
  • 0 -1 biểu thị phạm vi, trong đó 0 là giá trị bắt đầu và -1 đại diện cho mục cuối cùng của tập hợp.

Lệnh trên liệt kê tất cả các khóa mà không có SCORE của chúng. Chúng ta có thể khắc phục bằng cách thêm WITHSCORES 👇

// SCORE thấp nhất trước
zrange myPageCounts 0 -1 WITHSCORES
// SCORE cao nhất trước
zrevrange myPageCounts 0 -1 WITHSCORES
// lấy SCORE cho lượt truy cập page.home
zscore myPageCounts page.home

Khi bạn kiểm tra API và middleware, hãy chắc chắn kiểm tra bảng điều khiển Upstash để xem tất cả các hoạt động diễn ra trên trang web của bạn.

Khởi chạy Ứng dụng Nuxt 3 với Redis Serverless để Tăng Hiệu suất Nhanh chóng

Mức sử dụng tài nguyên trong bảng điều khiển Upstash

Triển khai ứng dụng Nuxt 3 của bạn

Nitro server engine đóng vai trò quan trọng khi triển khai ứng dụng Nuxt 3.

Netlify

Để triển khai trên Netlify, chúng ta sẽ đẩy repo GitHub của ứng dụng Nuxt như bình thường. Hãy đảm bảo bạn lo ba mục sau để triển khai suôn sẻ.

  • Trong Netlify, sử dụng npm run build làm lệnh build, và dist làm thư mục để publish.
  • Tạo biến môi trường cho rest-url, token hoặc kết nối Redis trong Netlify trước khi triển khai.
  • Cuối cùng nhưng không kém phần quan trọng, hãy đảm bảo bạn đã tạo netlify.toml
  • ở thư mục gốc của dự án Nuxt. Về nội dung file này, truy cập netlify.toml.

Khi chúng ta yarn build, Nuxt 3 tạo thư mục tên là .output mà chúng ta đã dùng trong file .toml để cung cấp đường dẫn cho các functions.

// netlify.toml
//...
[build]
// ...
functions = ".output/server";

Đây là ví dụ Nuxt từ bài viết này chạy trên Netlify: https://thirsty-visvesvaraya-a09ab9.netlify.app/

Cloudflare

Chúng ta có thể triển khai ứng dụng Nuxt 3 trên Cloudflare worker ngay từ terminal! Tài liệu Nuxt 3 khuyến nghị Miniflare để test ứng dụng cục bộ và sau đó dùng Wrangler để preview và publish.

Hãy chắc chắn thêm file wrangler.toml ở thư mục gốc dự án với account_id Cloudflare và biến môi trường như trong file ví dụ này.

Để triển khai trên Cloudflare, chúng ta sẽ cung cấp entry-point và lệnh build với NITRO_PRESET=cloudflare.

// wrangler.toml
//..
[site]
bucket = ".output/public"
entry-point = ".output"
[build]
command = "NITRO_PRESET=cloudflare yarn nuxt build"
upload.format = "service-worker"

Đây là ví dụ Nuxt từ bài viết này chạy trên Cloudflare worker: https://upstash-demo.krutie-patel.workers.dev/contact

Kết luận

Chúng ta đã bao gồm ứng dụng cơ bản nhất của Redis sử dụng dịch vụ Upstash để xem làm thế nào để tích hợp nó với framework server-side rendering như Nuxt (v3) để:

  • kết nối với cơ sở dữ liệu Redis,
  • tạo khóa duy nhất và ghi cặp key-value vào cơ sở dữ liệu,
  • đọc dữ liệu từ cơ sở dữ liệu Redis và
  • triển khai ứng dụng của chúng ta lên Netlify và Cloudflare workers.

Upstash cũng cung cấp tùy chọn mã hóa lưu lượng dữ liệu cho từng cơ sở dữ liệu chúng ta tạo, cùng với tùy chọn sao chép dữ liệu trong nhiều khu vực sẵn sàng (availability zones) và cache phản hồi REST API của chúng ta trên các vị trí edge phân tán toàn cầu. Bạn có thể tìm thấy các tùy chọn này trong bảng điều khiển Upstash, dưới tab details của cơ sở dữ liệu.

Đối với bất kỳ người mới bắt đầu nào muốn khám phá cơ sở dữ liệu Redis, Upstash làm cho việc bắt đầu trở nên khá dễ dàng về mặt làm việc với các công nghệ front-end sắp tới và hiện có mà chúng ta đã biết và yêu thích. Tôi hy vọng bài viết này cho bạn một điểm khởi đầu tốt để bắt đầu hành trình Redis của bạn.