Bộ đếm nguyên tử Python

Chúng tôi vui mừng thông báo rằng người dùng ứng dụng khách nâng cao dành cho Amazon DynamoDB trong AWS SDK cho Java 2. x giờ đây có thể kích hoạt bộ đếm nguyên tử, cũng như thêm các biểu thức cập nhật DynamoDB tùy chỉnh thông qua khung tiện ích máy khách nâng cao

Khách hàng đã nói với chúng tôi rằng họ muốn cải thiện hiệu suất và tính nhất quán khi cập nhật bản ghi bảng. Quy trình cập nhật bản ghi trong máy khách nâng cao DynamoDB thường có nghĩa là đọc một bản ghi từ cơ sở dữ liệu để truy cập các giá trị hiện tại trước khi ghi lại. Chi phí này có thể gây khó khăn nếu hồ sơ lớn và có thể phát sinh thêm chi phí. Hơn nữa, không có gì đảm bảo rằng bản ghi không được cập nhật giữa lần đọc và lần ghi. Điều này có nghĩa là nó không phải là một tập hợp các hành động nguyên tử

Thay đổi này có nghĩa là bạn có thể gắn thẻ thuộc tính bản ghi số dưới dạng bộ đếm nguyên tử và sử dụng DynamoDB để cập nhật thuộc tính với một giá trị cụ thể mỗi khi bạn gọi thao tác updateItem trên bảng của mình. Ngoài ra, chúng tôi đã giới thiệu một API mô hình hóa các biểu thức cập nhật. Điều này cho phép bạn viết các tiện ích mở rộng của riêng mình để trực tiếp tạo các biểu thức cập nhật ở cấp lược đồ cho DynamoDB

Các khái niệm

DynamoDB UpdateExpression – Đây là cú pháp được DynamoDB sử dụng khi gọi hoạt động

static final StaticTableSchema TABLE_SCHEMA=
    StaticTableSchema.builder[Customer.class]
                     .newItemSupplier[Customer::new]
                     .addAttribute[String.class, a -> a.name["id"] .. ]
                     .addAttribute[Long.class, a -> a.name["defaultCounter"]
                                                     .getter[Customer::getDefaultCounter]
                                                     .setter[Customer::setDefaultCounter]
                                                     .addTag[atomicCounter[]]]
                     .addAttribute[Long.class, a -> a.name["customCounter"]
                                                     .getter[Customer::getCustomCounter]
                                                     .setter[Customer::setCustomCounter]
                                                     .addTag[atomicCounter[5, 10]]]
                     .build[];
0 của nó. Sử dụng ứng dụng khách DynamoDB nâng cao để tự động tạo biểu thức này khi bạn cung cấp một mục để cập nhật

API UpdateExpression ứng dụng khách nâng cao – Đây là bản tóm tắt đại diện cho DynamoDB UpdateExpression trong ứng dụng khách nâng cao. Đọc thêm trong phần Giới thiệu về API UpdateExpression ứng dụng khách nâng cao sau trong bài đăng này

Tiện ích mở rộng máy khách nâng cao – Đây là lớp triển khai giao diện

static final StaticTableSchema TABLE_SCHEMA=
    StaticTableSchema.builder[Customer.class]
                     .newItemSupplier[Customer::new]
                     .addAttribute[String.class, a -> a.name["id"] .. ]
                     .addAttribute[Long.class, a -> a.name["defaultCounter"]
                                                     .getter[Customer::getDefaultCounter]
                                                     .setter[Customer::setDefaultCounter]
                                                     .addTag[atomicCounter[]]]
                     .addAttribute[Long.class, a -> a.name["customCounter"]
                                                     .getter[Customer::getCustomCounter]
                                                     .setter[Customer::setCustomCounter]
                                                     .addTag[atomicCounter[5, 10]]]
                     .build[];
1 nối với logic hoạt động, chẳng hạn như updateItem và cung cấp khả năng sửa đổi các yêu cầu hoặc tham số phản hồi

Chuỗi tiện ích mở rộng – Tất cả các tiện ích mở rộng được kích hoạt cho ứng dụng khách nâng cao. Các phần mở rộng trong chuỗi được áp dụng theo thứ tự

Sử dụng bộ đếm nguyên tử

Khi bạn muốn tạo bộ đếm nguyên tử và cập nhật DynamoDB mỗi khi bạn gọi thao tác updateItem, hãy tạo một thuộc tính bảng thuộc loại

static final StaticTableSchema TABLE_SCHEMA=
    StaticTableSchema.builder[Customer.class]
                     .newItemSupplier[Customer::new]
                     .addAttribute[String.class, a -> a.name["id"] .. ]
                     .addAttribute[Long.class, a -> a.name["defaultCounter"]
                                                     .getter[Customer::getDefaultCounter]
                                                     .setter[Customer::setDefaultCounter]
                                                     .addTag[atomicCounter[]]]
                     .addAttribute[Long.class, a -> a.name["customCounter"]
                                                     .getter[Customer::getCustomCounter]
                                                     .setter[Customer::setCustomCounter]
                                                     .addTag[atomicCounter[5, 10]]]
                     .build[];
4 đại diện cho bộ đếm và gắn thẻ cho nó là bộ đếm nguyên tử

Bạn kích hoạt chức năng bộ đếm nguyên tử khi khởi tạo ứng dụng khách nâng cao. Điều này là do nó tự động tải tiện ích mở rộng tương ứng,

static final StaticTableSchema TABLE_SCHEMA=
    StaticTableSchema.builder[Customer.class]
                     .newItemSupplier[Customer::new]
                     .addAttribute[String.class, a -> a.name["id"] .. ]
                     .addAttribute[Long.class, a -> a.name["defaultCounter"]
                                                     .getter[Customer::getDefaultCounter]
                                                     .setter[Customer::setDefaultCounter]
                                                     .addTag[atomicCounter[]]]
                     .addAttribute[Long.class, a -> a.name["customCounter"]
                                                     .getter[Customer::getCustomCounter]
                                                     .setter[Customer::setCustomCounter]
                                                     .addTag[atomicCounter[5, 10]]]
                     .build[];
5. Theo mặc định, bộ đếm bắt đầu từ 0 và tăng thêm 1 mỗi khi bản ghi trong bảng được cập nhật. Bạn có thể tùy chỉnh nó bằng cách thay đổi giá trị bắt đầu và/hoặc giá trị gia tăng, bao gồm cả giá trị âm

Giá trị bắt đầu được đặt khi

  • bạn gọi hoạt động updateItem và thuộc tính không tồn tại, hoặc
  • bạn gọi hoạt động
    static final StaticTableSchema TABLE_SCHEMA=
        StaticTableSchema.builder[Customer.class]
                         .newItemSupplier[Customer::new]
                         .addAttribute[String.class, a -> a.name["id"] .. ]
                         .addAttribute[Long.class, a -> a.name["defaultCounter"]
                                                         .getter[Customer::getDefaultCounter]
                                                         .setter[Customer::setDefaultCounter]
                                                         .addTag[atomicCounter[]]]
                         .addAttribute[Long.class, a -> a.name["customCounter"]
                                                         .getter[Customer::getCustomCounter]
                                                         .setter[Customer::setCustomCounter]
                                                         .addTag[atomicCounter[5, 10]]]
                         .build[];
    7

Ví dụ sau đây cho thấy cách tạo và sử dụng bộ đếm nguyên tử cho cả lược đồ bảng dựa trên bean và lược đồ bảng tĩnh

Bước 1. Xác định lược đồ với thuộc tính được gắn thẻ

lựa chọn 1. Lược đồ bảng dựa trên Bean
Tạo một thuộc tính thuộc loại Long và chú thích nó bằng

static final StaticTableSchema TABLE_SCHEMA=
    StaticTableSchema.builder[Customer.class]
                     .newItemSupplier[Customer::new]
                     .addAttribute[String.class, a -> a.name["id"] .. ]
                     .addAttribute[Long.class, a -> a.name["defaultCounter"]
                                                     .getter[Customer::getDefaultCounter]
                                                     .setter[Customer::setDefaultCounter]
                                                     .addTag[atomicCounter[]]]
                     .addAttribute[Long.class, a -> a.name["customCounter"]
                                                     .getter[Customer::getCustomCounter]
                                                     .setter[Customer::setCustomCounter]
                                                     .addTag[atomicCounter[5, 10]]]
                     .build[];
8

@DynamoDbBean
public class Customer {
  
    @DynamoDbPartitionKey
    public String getId[] { .. }
    public void setId[String id] { .. }

    @DynamoDbAtomicCounter
    public Long getUpdateCounter[] { .. }
    public void setUpdateCounter[Long counter] { .. }

    @DynamoDbAtomicCounter[delta = 5, startValue = 10]
    public Long getCustomCounter[] { .. }
    public void setCustomCounter[Long counter] { .. }
}

Lựa chọn 2. Lược đồ bảng bất biến tĩnh
Tạo thuộc tính StaticAttribute với loại thuộc tính

static final StaticTableSchema TABLE_SCHEMA=
    StaticTableSchema.builder[Customer.class]
                     .newItemSupplier[Customer::new]
                     .addAttribute[String.class, a -> a.name["id"] .. ]
                     .addAttribute[Long.class, a -> a.name["defaultCounter"]
                                                     .getter[Customer::getDefaultCounter]
                                                     .setter[Customer::setDefaultCounter]
                                                     .addTag[atomicCounter[]]]
                     .addAttribute[Long.class, a -> a.name["customCounter"]
                                                     .getter[Customer::getCustomCounter]
                                                     .setter[Customer::setCustomCounter]
                                                     .addTag[atomicCounter[5, 10]]]
                     .build[];
4 và sử dụng một trong các phương thức
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[];
TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema 
DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
0 để gắn thẻ thuộc tính

Ví dụ mã sau đây giả định rằng

DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[];
TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema 
DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
1 tồn tại và định nghĩa một lược đồ để tham chiếu lớp

static final StaticTableSchema TABLE_SCHEMA=
    StaticTableSchema.builder[Customer.class]
                     .newItemSupplier[Customer::new]
                     .addAttribute[String.class, a -> a.name["id"] .. ]
                     .addAttribute[Long.class, a -> a.name["defaultCounter"]
                                                     .getter[Customer::getDefaultCounter]
                                                     .setter[Customer::setDefaultCounter]
                                                     .addTag[atomicCounter[]]]
                     .addAttribute[Long.class, a -> a.name["customCounter"]
                                                     .getter[Customer::getCustomCounter]
                                                     .setter[Customer::setCustomCounter]
                                                     .addTag[atomicCounter[5, 10]]]
                     .build[];

Bước 2. Tạo một khách hàng và tài nguyên bảng

Khởi tạo ứng dụng khách DynamoDB nâng cao và tạo tài nguyên bảng bằng cách cung cấp cho nó lược đồ đã xác định trước đó

________số 8_______

Bước 3. Gọi cho DynamoDB

Khởi tạo đối tượng Khách hàng và đặt thuộc tính khóa. Sau đó, gọi updateItem

DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[];
TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema 
DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
3 để xác minh cập nhật tự động của các thuộc tính bộ đếm

Customer customer = Customer.builder[].id["SOME_ID"].build[]:

customerTable.updateItem[customer]; //both putItem and updateItem can be used to add records
Customer retrievedCustomer = customerTable.getItem[customer]

retrievedCustomer.defaultCounter[]; //the value is 0
retrievedCustomer.customCounter[];  //the value is 10

customerTable.updateItem[customer]; 

retrievedCustomer = customerTable.getItem[customer]
retrievedCustomer.defaultCounter[]; //the value is 1
retrievedCustomer.customCounter[];  //the value is 15

Như bạn có thể thấy, chúng tôi không tham chiếu các thuộc tính trong bản ghi được gửi tới DynamoDB. Tuy nhiên, bản ghi được cập nhật liên tục với các giá trị mỗi khi bạn gọi cơ sở dữ liệu. Đặt giá trị trên bản ghi theo cách thủ công sẽ khiến DynamoDB đưa ra một DynamoDBException, cho biết “Cập nhậtExpression không hợp lệ. Hai đường dẫn tài liệu trùng nhau […]”, bởi vì biểu thức cập nhật với bộ đếm được tạo tự động bởi

static final StaticTableSchema TABLE_SCHEMA=
    StaticTableSchema.builder[Customer.class]
                     .newItemSupplier[Customer::new]
                     .addAttribute[String.class, a -> a.name["id"] .. ]
                     .addAttribute[Long.class, a -> a.name["defaultCounter"]
                                                     .getter[Customer::getDefaultCounter]
                                                     .setter[Customer::setDefaultCounter]
                                                     .addTag[atomicCounter[]]]
                     .addAttribute[Long.class, a -> a.name["customCounter"]
                                                     .getter[Customer::getCustomCounter]
                                                     .setter[Customer::setCustomCounter]
                                                     .addTag[atomicCounter[5, 10]]]
                     .build[];
5 sẽ xung đột với biểu thức đã được tạo cho chính bản ghi đó

Tạo tiện ích mở rộng UpdateExpression tùy chỉnh

Viết tiện ích mở rộng của riêng bạn tận dụng tùy chọn mới để cung cấp

DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[];
TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema 
DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
5 tùy chỉnh trong khung tiện ích mở rộng

Cập nhật biểu thức trong phần mở rộng có thể áp dụng cho các trường hợp sử dụng mà bạn muốn thực hiện điều tương tự với một thuộc tính mỗi khi bạn gọi cơ sở dữ liệu, chẳng hạn như bộ đếm nguyên tử. Tuy nhiên, nếu bạn cần hiệu ứng một lần cho một yêu cầu, thì việc tận dụng khung tiện ích mở rộng sẽ không hữu ích. Trước khi xem xét hỗ trợ cho biểu thức cập nhật yêu cầu đơn lẻ, chúng tôi sẽ đánh giá việc sử dụng API UpdateExpression mới có trong bản phát hành này, cũng như phản hồi mà chúng tôi nhận được

Giới thiệu về API UpdateExpression ứng dụng khách nâng cao

UpdateExpression ứng dụng khách nâng cao bao gồm một hoặc nhiều UpdateAction tương ứng với cú pháp UpdateExpression của DynamoDB. Trước khi gửi yêu cầu cập nhật tới DynamoDB, máy khách nâng cao sẽ phân tích cú pháp UpdateExpression thành định dạng mà DynamoDB hiểu được

Ví dụ: bạn có thể tạo một RemoveAction sẽ xóa thuộc tính có tên “attr1” khỏi bản ghi

RemoveAction removeAction = 
    RemoveAction.builder[]
                .path["#attr1_ref"]
                .putExpressionName["#attr1_ref", "attr1"]
                .build[];

Lưu ý rằng, mặc dù việc sử dụng Tên biểu thức là tùy chọn, chúng tôi khuyên bạn nên sử dụng nó để tránh xung đột tên

Bước 1. Tạo một lớp mở rộng

Tạo một lớp mở rộng triển khai hook mở rộng

DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[];
TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema 
DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
6

public final class CustomExtension implements DynamoDbEnhancedClientExtension {

    @Override
    public WriteModification beforeWrite[DynamoDbExtensionContext.BeforeWrite context] {
        return WriteModification.builder[]
                                .updateExpression[createUpdateExpression[]]
                                .build[];
    }
}

Bạn có thể sử dụng đối tượng bối cảnh để lấy thông tin về những điều sau đây

  • Mục đã chuyển đổi
  • Siêu dữ liệu bảng, chẳng hạn như thẻ tùy chỉnh
  • Tên của hoạt động đang được gọi

Bước 2. Tạo UpdateExpression

Trong tiện ích mở rộng của chúng tôi, SetAction thay đổi giá trị của “attr2”, mà chúng tôi có thể suy ra là thuộc tính Chuỗi

private static UpdateExpression createUpdateExpression[] {
    AttributeValue newValue = AttributeValue.builder[].s["A new value"].build[];
    SetAction setAction = 
    SetAction.builder[]
                .path["#attr1_ref"]
                .value[":new_value"]
                .putExpressionName["#attr1_ref", "attr1"]
                .putExpressionValue[":new_value", newValue]
                .build[];

    UpdateExpression.builder[]
                    .addAction[setAction]
                    .build[];
}

Bước 3. Thêm tiện ích mở rộng cho khách hàng

Thêm tiện ích mở rộng tùy chỉnh của bạn vào ứng dụng khách

DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder[]
                                                              .extensions[new CustomExtension[]]]
                                                              .build[];

Bước 4. Gọi cho DynamoDB

Truy xuất một tham chiếu đến bảng và gọi updateItem

DynamoDbTable table = enhancedClient.table["tableName", tableSchema];
table.updateItem[new MyRecord[]];

Dưới mui xe

Có thể hữu ích khi hiểu cách hoạt động của khung tiện ích mở rộng và hoạt động UpdateItem để kết hợp đầu ra từ các tiện ích mở rộng với thông tin mục ở cấp độ yêu cầu để tạo thành một yêu cầu DynamoDB gắn kết

  • Nếu có một số tiện ích bổ sung thêm UpdateExpressions trong chuỗi tiện ích mở rộng, thì những tiện ích này sẽ được hợp nhất mà không có bất kỳ kiểm tra nào để tạo thành một biểu thức duy nhất
  • Mục được cập nhật được cung cấp bởi UpdateItemRequest nâng cao được chuyển đổi bởi thao tác thành một UpdateExpression nội bộ
  • UpdateExpression nội bộ trong hoạt động UpdateItem được hợp nhất với một từ khung tiện ích mở rộng – nếu nó tồn tại
  • DynamoDB chỉ cho phép một hành động thao tác trên một thuộc tính. Do đó, bất kỳ hành động trùng lặp nào tham chiếu đến cùng một thuộc tính sẽ không thành công cục bộ trong máy khách khi UpdateExpression được phân tích cú pháp thành yêu cầu DynamoDB cấp thấp
  • Ứng dụng khách nâng cao tạo các câu lệnh xóa cho bất kỳ thuộc tính nào không được đặt rõ ràng trên một mục được cung cấp cho hoạt động UpdateItem. Vì hành vi mặc định này [được kiểm soát bởi cờ
    DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.create[];
    TableSchema tableSchema = TableSchema.fromBean[Customer.class]; // or TABLE_SCHEMA for static schema 
    DynamoDbTable customerTable = enhancedClient.table["customers_table", tableSchema];
    7] can thiệp vào chức năng của tiện ích mở rộng nên ứng dụng khách sẽ tự động lọc các thuộc tính đó bằng cách kiểm tra xem chúng có xuất hiện trong tiện ích mở rộng UpdateExpression hay không. Nếu có, thì khách hàng không tạo câu lệnh loại bỏ cho họ

Phần kết luận

Trong bài đăng này, bạn đã học cách sử dụng bộ đếm nguyên tử trong ứng dụng khách DynamoDB nâng cao và bạn đã thấy cách các tiện ích mở rộng có thể hoạt động với API UpdateExpression nâng cao cho các ứng dụng tùy chỉnh. Ứng dụng khách nâng cao là mã nguồn mở và nằm trong cùng một kho lưu trữ với AWS SDK cho Java 2. 0

Chúng tôi hy vọng bạn thấy bài đăng này hữu ích và chúng tôi mong nhận được phản hồi của bạn. Bạn luôn có thể chia sẻ thông tin đầu vào của mình trên trang vấn đề GitHub của chúng tôi hoặc bỏ phiếu ủng hộ các ý tưởng khác cho các tính năng mà bạn muốn thấy trong ứng dụng khách nâng cao DynamoDB hoặc AWS SDK dành cho Java nói chung

Anna-Karin là người duy trì AWS SDK cho Java. Cô ấy có niềm đam mê viết phần mềm và cơ sở hạ tầng có thể bảo trì, cũng như thích làm vườn, đi bộ đường dài và vẽ tranh. Bạn có thể tìm thấy cô ấy trên GitHub @cenedhryn

Hoạt động nguyên tử trong Python là gì?

Một thao tác nguyên tử là một hoặc một chuỗi các lệnh mã được hoàn thành mà không bị gián đoạn . Một chương trình có thể bị gián đoạn vì một trong nhiều lý do. Trong lập trình đồng thời, một chương trình có thể bị gián đoạn thông qua chuyển ngữ cảnh. Bạn có thể nhớ lại rằng hệ điều hành kiểm soát những luồng nào thực thi và khi nào.

Python có tăng nguyên tử không?

Không có sửa đổi nguyên tử nào trong Python trừ khi bạn sử dụng pypy [nếu bạn làm như vậy, hãy xem __pypy__.

Là chủ đề số nguyên Python

Int trong Python là bất biến, nghĩa là không thể sửa đổi nó sau này và bất kỳ thay đổi giá trị nào cũng là một quá trình gán một đối tượng Int bất biến mới cho đối tượng ban đầu. Nhưng điều đó không bao giờ có nghĩa là bất kỳ thao tác nào trong cú pháp Python là an toàn cho luồng, kể cả các hiệu ứng GIL . Ví dụ. x+=1 hoàn toàn không an toàn cho luồng.

Là chủ đề cấu trúc dữ liệu Python

Chúng an toàn cho chuỗi miễn là bạn không tắt mã GIL trong C cho chuỗi .

Chủ Đề