在 Linux 服务器上使用 Golang 和 MySQL 实现 Redis 事务和锁

一、介绍

在 Redis 中,事务是由必须以原子方式提交的多个命令组成的单个工作单元。也就是说,要么执行所有命令,要么不执行任何命令。Redis 使用 、、 和 函数来实现此功能。MULTIEXECDISCARDWATCH

要通过该工具创建事务,您只需先运行命令,然后运行其他后续命令。最后,应执行命令来处理事务或命令刷新排队的命令。redis-cliMULTIEXECDISCARD

该命令允许您在事务的生存期内实现锁定机制,如果您的密钥被另一个会话修改,该命令应无法避免将 Redis 数据库置于不一致状态。WATCHWATCHedEXEC

在本指南中,您将使用 Redis 事务函数在 Linux 服务器上使用 Golang 和 MySQL 创建抢票应用程序。

二、准备工作

若要继续本教程,请确保具有以下各项:

  • 一个 Linux 服务器。
  • 具有 sudo 权限的非 root 用户。
  • 一个MySQL服务器。
  • 一个 Redis 服务器。
  • 一个戈朗包。

三、 创建 MySQL 数据库、用户帐户和表

Redis 是一个内存数据库,虽然它可以将数据持久保存到磁盘,但它不是为此目的而设计的,可能无法以最佳方式执行。因此,在本指南中,您将使用 MySQL 数据库在 Redis 服务器生成票证信息后将其永久存储到 MySQL 表中。

通过 SSH 连接到您的服务器,然后按照以下步骤创建数据库。

    1. 以 身份登录到 MySQL 服务器。root
      $ sudo mysql -uroot -p
    2. 出现提示时输入您的 MySQL 密码,然后按继续。然后,执行以下命令以创建数据库和帐户。替换为强值。rootENTERbookingsbookings_userEXAMPLE_PASSWORD
      mysql> CREATE DATABASE bookings DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
      
             CREATE USER 'bookings_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'EXAMPLE_PASSWORD';
      
             GRANT ALL PRIVILEGES ON bookings.* TO 'bookings_user'@'localhost';
      
             FLUSH PRIVILEGES;
    3. 切换到新数据库。
      mysql> USE bookings;
    4. 接下来,创建一个表。在此示例应用程序中,您将使用 Redis 服务器从可用座位池中抓取乘客的座位。然后,您将在表中永久存储分配的信息和信息。ticketsseat_no'sticket_id'stickets
      mysql> CREATE TABLE tickets (
      
                 ticket_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
      
                 seat_no BIGINT    
      
             ) ENGINE = InnoDB;
    5. 您的数据库、用户帐户和表现已就位。从 MySQL 服务器注销。
      mysql> QUIT;

      在下一步中,您将创建一个 Golang 脚本来接受通过 HTTPS 传入的工单请求。

四、创建文件main.go

要将此应用程序与其他 Linux 文件分开,您需要一个单独的源代码目录。

  1. 创建目录.project
    $ mkdir project
  2. 然后,切换到新目录.project
    $ cd project
  3. 接下来,用于创建文件。此文件包含运行应用程序时触发的主脚本.nanomain.go
    $ nano main.go
  4. With the file opened, paste the following information into the file.main.go
    package main
    
    
    
    import (
    
    "encoding/json"
    
    "fmt"
    
    "net/http"
    
    "strconv"
    
    )
    
    
    
    func main() {
    
        http.HandleFunc("/tickets", httpHandler)            
    
        http.ListenAndServe(":8080", nil)
    
    }
    
    
    
    func httpHandler(w http.ResponseWriter, req *http.Request) { 
    
    
    
        var err error
    
        resp := map[string]interface{}{}
    
    
    
        resp, err = newTicket() 
    
    
    
        enc := json.NewEncoder(w)
    
        enc.SetIndent("", "  ") 
    
    
    
        if err != nil {
    
            resp = map[string]interface{}{"error": err.Error(),}     
    
        }
    
    
    
        if err := enc.Encode(resp); err != nil {
    
            fmt.Println(err.Error())
    
        }
    
    
    
    }
    
    
    
    func newTicket() (map[string]interface{}, error) {
    
    
    
        seatNo, err := createTicket("test")
    
    
    
        if err != nil {
    
            return nil, err
    
        }
    
    
    
        resp := map[string]interface{}{"Response" : "Seat # " + strconv.FormatInt(seatNo, 10) + " booked successfully.",}
    
    
    
        return resp, nil          
    
    
    
    }
  5. Save and close the file when you’re through with editing.
  6. 在上面的文件中,你将导入包,该包允许你格式化 JSON 数据。接下来,你已包含用于格式化和输出字符串的包。该包允许您将其他数据类型转换为字符串格式,同时库提供 HTTP 实现。main.goencoding/jsonfmtstrconvnet/http
  7. 在 main 函数 () 下,您正在侦听 URL 中端口上的传入 HTTP 请求。然后,您将 HTTP 请求重定向到函数,该函数又使用该语句调用该函数。func main() {...}8080/ticketsfunc httpHandler(){...}newTicket()resp, err = newTicket()
  8. 在该函数下,您将使用该语句调用该函数,以从 Redis 服务器获取乘客的座位号。在下一步中,您将在新文件中创建函数。func newTicket(){}createTicket(...)seatNo, err := createTicket("test")createTicket(...)tickets.go

五、 创建文件tickets.go

在此步骤中,您将创建一个连接到 Redis 服务器的 Golang 脚本。首先,脚本将读取一个键,用于检查可供预订的座位总数。然后,如果剩余席位数大于或等于 1,则脚本将保留一个席位号,将剩余席位数减 1 并返回分配给调用脚本的席位。testseat_no

  1. 用于创建文件。nanotickets.go
    $ nano tickets.go
  2. 然后,在文件中输入以下信息。tickets.go
    package main
    
    
    
    import (
    
    "context"
    
    "errors"
    
    "strconv"
    
    "github.com/go-redis/redis"
    
    )
    
    
    
    func createTicket(key string) (int64, error) {
    
    
    
        ctx := context.Background()
    
    
    
        redisClient := redis.NewClient(&redis.Options{
    
            Addr: "localhost:6379",
    
            Password: "",
    
            DB: 0,
    
        })
    
    
    
        var seatNo int64
    
    
    
        err := redisClient.Watch(ctx, func(tx *redis.Tx) error {
    
    
    
            val, err := tx.Get(ctx, key).Int64()
    
    
    
            if err != nil && err != redis.Nil {
    
                return err
    
            }
    
    
    
            seatNo = val
    
    
    
            if (seatNo - 1) < 0 {
    
                return errors.New("Unable to secure a seat.\r\n")
    
            }
    
    
    
            _, err = tx.Pipelined(ctx, func(pipe redis.Pipeliner) error {
    
    
    
                pipe.Set(ctx, key, strconv.FormatInt(seatNo - 1, 10), 0)    
    
    
    
                return nil
    
            })
    
    
    
            if err == nil {
    
                insertRecord(seatNo)
    
            }
    
    
    
    return err
    
    
    
    }, key)
    
    
    
        if err == redis.TxFailedErr {               
    
            return createTicket(key)
    
    }
    
    
    
    return seatNo, err
    
    }
  3. 保存并关闭文件。
  4. 在上面的文件中,您已导入包,以使用语句为 Redis 调用提供不受限制的截止时间。然后,使用包将自定义错误返回到调用函数。该软件包允许您在 Golang 脚本中实现 Redis 函数。contextctx := context.Background()errorsgithub.com/go-redis/redis
  5. 在 中,您接受 1 个参数。这是您用于在应用程序中保留可用席位的名称。在本教程中,你将用作键名称。在生产环境中,您可以考虑使用更有意义/更具描述性的名称,例如 。func createTicket(key string) (int64, error){}keytestavailable_seats
  6. 该语句允许您连接并创建新的 Redis 客户端实例。然后,您使用语句初始化一个空变量。脚本分配座位号后,您将填充此变量。redisClient := redis.NewClient(...)seatNovar seatNo int64
  7. 接下来,您将使用 Redis 函数,该语句在事务的生存期内监视密钥。如果另一个会话以任何方式修改了密钥,则整个事务应中止,并且您已对脚本进行了编码,以便使用语句重试脚本。请记住,在生产环境中,客户可以从不同的应用程序(例如移动应用程序、API、桌面应用程序、门户等)购买票证。这里的想法是一次发行一张票以避免超额预订。WATCHerr := redisClient.Watch(ctx, func()...{...}, key)testtestif err == redis.TxFailedErr { return createTicket(key) }
  8. 在函数内部,您可以使用语句检索剩余席位的值。如果没有剩余席位,您将使用 语句 抛出自定义错误。WATCHval, err := tx.Get(ctx, key).Int64()if (seatNo - 1) < 0 { return errors.New("Unable to secure a seat.\r\n") }
  9. 接下来,预订座位后,您将使用语句减少可用座位数。Redis 管道允许您在一次网络调用中将多个命令传输到 Redis 服务器。在本教程中仅执行一个命令时,应始终使用管道模型,以便在应用程序逻辑发生更改时更轻松地进行修改。pipe.Set(ctx, key, strconv.FormatInt(seatNo - 1, 10), 0)
  10. 然后,您调用该函数以将票证信息保存到 MySQL 数据库,以防使用该语句执行流水线命令时没有错误。一旦整个函数运行,它应该返回文件或任何错误,以防遇到任何错误。insertRecord()if err == nil { insertRecord(seatNo) }createTicket()seatNomain.go
  11. 在下一步中,您将在不同的文件中创建要在此调用的函数。insertRecord()tickets.godatabase.go

六、创建文件database.go

您将为此抢票应用程序创建的最后一个脚本是文件。此文件包含将票证信息永久存储到 MySQL 数据库的逻辑。database.go

  1. 使用 Nano 创建文件。database.go
    $ nano database.go
  2. 然后,在文件中输入以下信息。database.go
    package main
    
    
    
    import (
    
        "database/sql"
    
        _ "github.com/go-sql-driver/mysql"      
    
    )
    
    
    
    func insertRecord(seatNo int64) error {
    
    
    
        dbUser     := "bookings_user"
    
        dbPassword := "EXAMPLE_PASSWORD"
    
        dbName     := "bookings"
    
    
    
        db, err := sql.Open("mysql", dbUser + ":" + dbPassword + "@tcp(127.0.0.1:3306)/" + dbName) 
    
    
    
        if err != nil {
    
            return err
    
        }
    
    
    
        defer db.Close()
    
    
    
        queryString := "insert into tickets (seat_no) values (?)"
    
    
    
        stmt, err   := db.Prepare(queryString) 
    
    
    
        if err != nil {
    
            return err       
    
        }
    
    
    
        defer stmt.Close()     
    
    
    
        _, err = stmt.Exec(seatNo) 
    
    
    
        if err != nil {
    
            return err
    
        }
    
    
    
        return nil
    
    }
  3. 保存并关闭文件。
  4. 在上面的文件中,你正在使用 and 包来实现 Golang 中的 SQL 和 MySQL 功能。在该函数下,你将使用之前创建的凭据连接到 MySQL 数据库。然后,您将工单信息保存到表中。database/sqlgithub.com/go-sql-driver/mysqlfunc insertRecord(...) error {...}tickets
  5. 现在,您已经编写了使用 MySQL 和 Golang 运行 Redis 事务的所有脚本。在下一步中,您将测试一切是否按预期工作。

七、 测试 Redis 事务应用程序

您的 Golang 事务应用程序现在已经准备好进行测试了。

  1. 在执行应用程序之前,请导入已在应用程序中实现的所有包。
    $ go get github.com/go-redis/redis
    
    $ go get github.com/go-sql-driver/mysql
  2. 接下来,打开 Redis 命令行界面。
    $ redis-cli
  3. 通过将键的值设置为 .10test10
    $ SET test 10
  4. 从 Redis 服务器注销。
    $ QUIT
  5. 确保您仍在目录下,然后执行以下命令以运行 Golang 应用程序。project
    $ go run ./
  6. 上面的命令有一个阻塞功能,可以在端口下旋转 Web 服务器。不要在此终端窗口上运行任何其他命令。8080
  7. 接下来,在新的终端窗口中通过 SSH 连接到您的服务器并安装 Apache Bench () 软件包。你将使用此工具向应用程序发送并行票证请求命令,以查看它是否可以处理事务,而不会出现任何超额预订或争用情况。ab
    $ sudo apt install -y apache2-utils
  8. 接下来,向应用程序发送并行票证请求。请记住,您只在 Redis 服务器中使用了席位。因此,只有事务应该成功,其余事务应该失败。此外,由于您已使用该函数实现了 Redis 锁,因此不应出现不同会话具有相同情况的情况。201010seat_noWATCH
    $ ab -v 2 -n 20 -c 20 http://localhost:8080/tickets
  9. 您应该会收到以下响应。
    ...
    
    {
    
      "Response": "Seat # n booked successfully."
    
    }
    
    
    
    ...
    
    
    
    {
    
      "error": "Unable to secure a seat.\r\n"
    
    }
    
    
    
    ...
  10. 接下来,在仍然登录到第二个终端窗口的同时,登录到MySQL数据库以确认新的更改。root
    $ sudo mysql -u root -p
  11. 输入 MySQL 服务器的密码,然后按继续。然后,切换到数据库。rootENTERbooking
    mysql> USE bookings;
  12. 对表运行语句。SELECTtickets
    mysql> SELECT
    
               ticket_id,
    
               seat_no
    
           FROM tickets;
  13. 您现在应该看到以下票证和关联的 .从以下输出中可以看出,没有超额预订的情况。此外,该脚本已成功消除了任何竞争条件的机会,因为没有两张票具有相同的。seat_no'sseat_no
    +-----------+---------+
    
    | ticket_id | seat_no |
    
    +-----------+---------+
    
    |         1 |      10 |
    
    |         2 |       9 |
    
    |         3 |       7 |
    
    |         4 |       8 |
    
    |         5 |       6 |
    
    |         6 |       5 |
    
    |         7 |       3 |
    
    |         8 |       4 |
    
    |         9 |       1 |
    
    |        10 |       2 |
    
    +-----------+---------+
    
    10 rows in set (0.00 sec)
  14. 您的脚本现在按预期工作。

八、结论

在本指南中,您已经在 Linux 服务器中实现了 Redis 事务并使用 Golang 和 MySQL 数据库锁定,以创建抢票应用程序。使用本指南中的逻辑可避免在创建多用户应用程序时出现争用条件和数据库不一致。

教程:在 Python 中实现购物车,使用 Vultr 托管数据库进行 Redis

一、介绍

Redis 服务器是使用最广泛的开源数据库解决方案之一。Redis 将所有数据存储在内存中,以实现低延迟和高吞吐量。这些优势使 Redis 适用于存储繁忙网站的购物车数据,尤其是在旺季。

从电子商务网站下订单时,客户通常会从购物清单中选择商品,然后将商品添加到购物车。在后台,购物车驻留在数据库中。虽然使用关系数据库来处理购物车数据是可行的,但此类数据库可能无法在大量用户的情况下以最佳方式执行,并且它们的缓慢可能会对用户体验产生负面影响。

Redis 具有多种功能,您可以使用它们来加快在网站上添加、删除和显示购物车数据的过程。您可以将 Redis,,, 和命令与 Redis 哈希(字段值对的集合)结合使用,以实现所有购物车功能。hsethincrbyhdelhget

本指南向您展示如何在 Ubuntu 20.04 服务器上使用 Python 和托管 Redis 数据库实现购物车应用程序。

二、准备工作

要遵循本指南:

  • 部署 Ubuntu 20.04 服务器。
  • 创建一个非根sudo用户。
  • 配置托管的 Vultr Redis 数据库。然后,导航到您的 Redis 数据库实例并单击概述选项卡以检索您的数据库连接详细信息。本指南使用以下示例连接详细信息:
    • 用户名default
    • 密码EXAMPLE_PASSWORD
    • 主持人SAMPLE_DB_HOST_STRING.vultrdb.com
    • 端口16752

三、创建中央 Redis 类

在设计 Python 应用程序时,通常为基本函数设置单独的类,以促进代码重用并减少重复。本指南使用一个中央 Redis 类,该类处理从 Redis 服务器添加、删除、删除和列出购物车项目的不同功能。按照以下步骤创建类:

  1. 首先创建一个目录,将你的 Python 源代码与其他 Linux 文件分开。project
    $ mkdir project
  2. 切换到新目录。project
    $ cd project
  3. 在文本编辑器中打开一个新文件。redis_gateway.py
    $ nano redis_gateway.py
  4. 在文件中输入以下信息。将 、 和值替换为托管 Redis 数据库中的正确数据库信息。redis_gateway.pydb_hostdb_portdb_pass
    import redis
    
    
    
    class RedisGateway:
    
    
    
        def __init__(self):
    
    
    
            db_host = 'SAMPLE_DB_HOST_STRING.vultrdb.com'
    
            db_port = 16752
    
            db_pass = 'EXAMPLE_PASSWORD'   
    
    
    
            self.redisClient = redis.Redis(host = db_host, port = db_port, password = db_pass, ssl = 'true')
    
    
    
        def add_to_cart(self, json_payload):
    
    
    
            cart_id = json_payload["cart_id"]
    
            product_name = json_payload["product_name"]
    
            quantity = json_payload["quantity"]
    
    
    
            if self.redisClient.hexists(cart_id , product_name):
    
    
    
                self.redisClient.hincrby(cart_id , product_name, quantity)
    
    
    
            else:   
    
    
    
                self.redisClient.hset(cart_id, product_name, quantity)                   
    
    
    
            return "Item added to cart successfully."
    
    
    
        def remove_from_cart(self, json_payload):
    
    
    
            cart_id = json_payload["cart_id"]
    
            product_name = json_payload["product_name"]
    
    
    
    
    
            if self.redisClient.hexists(cart_id, product_name):
    
    
    
                self.redisClient.hdel(cart_id, product_name)
    
    
    
                return "Item removed from cart."
    
    
    
            else:   
    
    
    
                return "Item not found from cart."
    
    
    
        def get_cart(self, cart_id):
    
    
    
            result = self.redisClient.hgetall(cart_id)        
    
    
    
            return result
  5. 保存并关闭文件。redis_gateway.py

3.1、redis_gateway.py文件解释

  • 该文件有一个类。redis_gateway.pyRedisGateway
  • 该类有四种方法。RedisGateway
    1. 该函数在首次导入和初始化类时触发。__init__()
    2. 该函数包含您要添加到购物车的、该和该。在函数下,您首先通过运行函数来检查 Redis 服务器中是否存在购物车。如果购物车存在,则使用命令将新数量添加到购物车。否则,如果具有定义的购物车不存在,则从头开始创建它。然后,您将使用该命令添加新的产品名称和数量。add_to_cart(..., json_payload)json_payloadcart_idproduct_namequantityadd_to_cart()self.redisClient.hexistsself.redisClient.hincrby...cart_idself.redisClient.hset(cart_id, product_name, quantity)
    3. 该函数接受具有要从购物车中删除的产品名称的 JSON 有效负载。在发出命令之前,您使用逻辑语句检查产品是否存在于 Redis 服务器中。remove_from_cart(self, json_payload)if self.redisClient.hexists(cart_id, product_name):self.redisClient.hdel(cart_id, product_name)
    4. 该函数采用并查询 Redis 服务器以使用命令列出购物车中的所有项目。get_cart(..., cart_id)cart_idself.redisClient.hgetall(cart_id)
  • 现在准备好了。您可以在其他源代码文件中引用它,并使用以下语法使用其方法:RedisGateway
    import redis_gateway  
    
    rg = redis_gateway.RedisGateway()
    
    
    
    resp = rg.add_to_cart(json_payload);
    
    resp = rg.remove_from_cart(json_payload);
    
    resp = rg.get_cart(cart_id);

准备好中央 Redis 网关后,按照下一步为您的应用程序创建主文件。

四、 创建主 Python 文件

每个 Python 应用程序都必须有一个在启动应用程序时触发的主文件。本指南使用文件作为起点。按照以下步骤创建文件:main.py

  1. 在文本编辑器中打开一个新文件。main.py
    $ nano main.py
  2. 在文件中输入以下信息。main.py
    import http.server
    
    from http import HTTPStatus
    
    from urllib.parse import urlparse, parse_qs
    
    
    
    import socketserver
    
    import json
    
    
    
    import redis_gateway        
    
    
    
    class httpHandler(http.server.SimpleHTTPRequestHandler):
    
    
    
        def do_POST(self):
    
    
    
            content_length = int(self.headers['Content-Length'])
    
            post_data = self.rfile.read(content_length)
    
    
    
            json_payload = json.loads(post_data) 
    
    
    
            self.send_response(HTTPStatus.OK)
    
            self.end_headers()
    
    
    
            rg = redis_gateway.RedisGateway()
    
    
    
            resp = rg.add_to_cart(json_payload);                
    
    
    
            self.wfile.write(bytes(resp + '\r\n', "utf8"))
    
    
    
        def do_DELETE(self):
    
    
    
            content_length = int(self.headers['Content-Length'])
    
            post_data = self.rfile.read(content_length)
    
    
    
            json_payload = json.loads(post_data) 
    
    
    
            self.send_response(HTTPStatus.OK)
    
            self.end_headers()
    
    
    
            rg = redis_gateway.RedisGateway()
    
    
    
            resp = rg.remove_from_cart(json_payload);                
    
    
    
            self.wfile.write(bytes(resp + '\r\n', "utf8"))
    
    
    
        def do_GET(self):
    
    
    
            self.send_response(HTTPStatus.OK)
    
            self.end_headers()
    
    
    
            parsed_url = urlparse(self.path)
    
            params = parse_qs(parsed_url.query)
    
    
    
            cart_id = params['cart_id'][0]
    
    
    
            rg = redis_gateway.RedisGateway()  
    
    
    
            cart = rg.get_cart(cart_id)
    
    
    
            data = { y.decode('ascii'): cart.get(y).decode('ascii') for y in cart.keys() }
    
    
    
            resp = json.dumps(data, indent = 4, separators = (',', ': '))    
    
    
    
            self.wfile.write(bytes(resp + "\r\n", "utf8"))
    
    
    
    httpServer = socketserver.TCPServer(('', 8080), httpHandler)
    
    
    
    print("HTTP server started at port 8080...")
    
    
    
    try:
    
    
    
        httpServer.serve_forever()
    
    
    
    except KeyboardInterrupt:
    
    
    
        httpServer.server_close()
    
        print("The server is stopped.")
  3. 保存并关闭文件。main.py

4.1、main.py 文件解释

  • 该部分允许您导入应用程序所需的所有必要的 Python 模块。,,,, 和模块为应用程序提供 HTTP 功能。该模块允许您在标准 JSON 响应中格式化响应。然后,要连接到 Redis 服务器,您需要导入自定义模块。import ...http.serverHTTPStatusurlparseparse_qssocketserverjsonredis_gateway
  • 该类处理所有 HTTP 方法。这些是,,,和。这些方法与以下购物车功能匹配。httpHandlerPOSTDELETEGET
    • POST:.将商品添加到购物车。rg.add_to_cart(...)
    • DELETE:.从购物车中删除商品。rg.remove_from_cart(...)
    • GET:.列出购物车中的所有商品。rg.get_cart(...)
  • 该语句在端口上启动 HTTP 服务器并声明为处理程序类。httpServer = socketserver.TCPServer(('', 8080), httpHandler)8080httpHandler

您的应用程序现已准备就绪。按照下一步测试应用程序。

五、 测试 Redis 购物车应用程序

最后一步是安装应用程序所需的第三方 Python 模块,并运行一些测试以确保一切正常。

  1. 安装 Python 包。这是一个用于下载和安装Python模块的工具。pip
    $ sudo apt update
    
    $ sudo apt install -y python3-pip
  2. 使用软件包来安装 Python 模块。pipredis
    $ pip install redis
  3. 使用命令运行应用程序,然后使用启动文件。python3main.py
    $ python3 main.py

    输出。

    HTTP server started at port 8080...
  4. 与服务器建立另一个 SSH 连接,并使用 Linux命令向应用程序发送以下请求。curl
    • 将三个项目添加到购物车使用。abccart_id
      $ curl -X POST http://localhost:8080/ -H 'Content-Type: application/json' -d '{"cart_id": "abc", "product_name": "SMART WATCH", "quantity": "4"}'
      
      
      
      $ curl -X POST http://localhost:8080/ -H 'Content-Type: application/json' -d '{"cart_id": "abc", "product_name": "4G WIRELESS ROUTER", "quantity": "7"}'
      
      
      
      $ curl -X POST http://localhost:8080/ -H 'Content-Type: application/json' -d '{"cart_id": "abc", "product_name": "500W JUICER", "quantity": "2"}'

      输出。

      ...
      
      Item added to cart successfully.
    • 从购物车中检索商品。
      $ curl -X GET 'http://localhost:8080?cart_id=abc'

      输出。

      {
      
          "SMART WATCH": "4",
      
          "4G WIRELESS ROUTER": "7",
      
          "500W JUICER": "2"
      
      }
    • 从购物车中取出一件商品。
      $ curl -X DELETE http://localhost:8080/ -H 'Content-Type: application/json' -d '{"cart_id": "abc", "product_name": "SMART WATCH"}'

      输出。

      Item removed from cart.

 六、结论

本指南在 Ubuntu 20.04 服务器上使用 Python 和来自 Vultr 的托管 Redis 数据库实现了购物车解决方案。在创建下一个购物车应用程序时,请使用本指南中的示例源代码。Redis 购物车实现允许您的应用程序在高峰期处理许多订单,从而增强用户体验。