cuốn sách gpt4 ai đã làm

Các giải pháp tạo ID phân tán phổ biến

In lại Tác giả: Người biết Thời gian cập nhật: 2024-03-13 02:58:32 31 4
mua khóa gpt4 Nike

1. Tại sao nên sử dụng ID phân tán?

Trước khi nói về cách triển khai cụ thể của ID phân tán, hãy phân tích ngắn gọn lý do tại sao ID phân tán được sử dụng? ID được phân phối phải đáp ứng những đặc điểm nào?

1. ID phân phối là gì?

Lấy cơ sở dữ liệu MySQL làm ví dụ:

Khi lượng dữ liệu kinh doanh của chúng tôi không lớn, một cơ sở dữ liệu và một bảng duy nhất có thể hỗ trợ đầy đủ cho doanh nghiệp hiện có. Ngay cả khi dữ liệu lớn hơn, nó có thể được xử lý bằng cách phân tách đọc-ghi đồng bộ giữa chủ và phụ của MySQL.

Tuy nhiên, khi dữ liệu tăng lên từng ngày, không thể duy trì đồng bộ hóa chủ-nô, do đó cơ sở dữ liệu cần được chia thành cơ sở dữ liệu và bảng. Tuy nhiên, sau khi cơ sở dữ liệu được chia thành các bảng, cần có một ID duy nhất để xác định một phần. của dữ liệu. ID tự tăng của cơ sở dữ liệu rõ ràng là không đủ. Nhu cầu cũng cần có những ID đặc biệt như đơn đặt hàng và phiếu giảm giá.ID duy nhấtLàm logo. Tại thời điểm này a có thể được tạo raID duy nhất trên toàn cầuhệ thống là rất cần thiết. Thế thì cái nàyID duy nhất trên toàn cầuChỉ cần gọiID phân phối

2. Vậy ID được phân phối cần đáp ứng những điều kiện gì?

  • Duy nhất toàn cầu: ID phải là duy nhất trên toàn cầu, một yêu cầu cơ bản
  • Hiệu suất cao: tính sẵn sàng cao và độ trễ thấp, phản hồi tạo ID phải nhanh, nếu không sẽ trở thành nút thắt cổ chai trong kinh doanh
  • Tính sẵn sàng cao: Hệ thống tạo số ID có yêu cầu về tính sẵn sàng cực kỳ cao nên không thể có một điểm lỗi nào.
  • Khả năng tiếp cận tốt: Cần tuân thủ nguyên tắc thiết kế sẵn sàng sử dụng, đồng thời việc thiết kế và triển khai hệ thống phải đơn giản nhất có thể.
  • Xu hướng ngày càng tăng: Các chỉ mục được nhóm được sử dụng trong công cụ MySQL InnoDB Vì hầu hết RDBMS sử dụng cấu trúc dữ liệu cây B để lưu trữ dữ liệu chỉ mục, nên khi chọn khóa chính, chúng ta nên cố gắng sử dụng các khóa chính theo thứ tự để đảm bảo hiệu suất ghi.
  • Tăng đơn điệu: Đảm bảo ID tiếp theo phải lớn hơn ID trước đó, chẳng hạn như số phiên bản giao dịch, tin nhắn gia tăng IM, sắp xếp và các yêu cầu đặc biệt khác
  • Bảo mật thông tin: Nếu ID liên tục, người dùng độc hại sẽ rất dễ dàng lấy cắp thông tin. Họ chỉ cần tải xuống URL được chỉ định theo thứ tự. Nếu là số thứ tự, đối thủ cạnh tranh có thể trực tiếp biết được. khối lượng đặt hàng hàng ngày của chúng tôi. Do đó, trong một số trường hợp ứng dụng, ID có thể cần phải không đều đặn hoặc không đều.
  • Hỗ trợ Sharding: ShardingId có thể được kiểm soát. Ví dụ: các bài viết của người dùng phải được đặt trong cùng một phân đoạn để hiệu quả truy vấn cao và dễ dàng sửa đổi.

2. Có những cách nào để tạo ID phân tán?

Hôm nay chúng ta sẽ chủ yếu phân tích 9 phương pháp tạo ID phân tán sau đây cũng như những ưu điểm và nhược điểm của chúng:

  • Dựa trên UUID
  • ID tăng dựa trên cơ sở dữ liệu
  • Dựa trên chế độ cụm cơ sở dữ liệu
  • Mẫu phân đoạn số dựa trên cơ sở dữ liệu
  • Dựa trên chế độ Redis
  • Dựa trên thuật toán SnowFlake
  • Baidu(Uidgenerator)
  • Meituan (Lá)
  • Sản xuất bởi Didi (TinyID)

Vậy chúng được thực hiện như thế nào? Và ưu nhược điểm của mỗi loại là gì? Hãy nhìn xuống

1. Dựa trên UUID

UUID (Mã định danh duy nhất toàn cầu), tên viết tắt của Mã định danh duy nhất toàn cầu. UUID bao gồm một tập hợp các số thập lục phân gồm 32 chữ số, do đó tổng số UUID theo lý thuyết là 1632=2128, xấp xỉ bằng 3,4 x 10^38. Nói cách khác, nếu 1 nghìn tỷ UUID được tạo ra mỗi nano giây thì sẽ mất 10 tỷ năm để sử dụng hết tất cả UUID.

UUID được tạo bởi 8-4-4-4-12Dữ liệu định dạng bao gồm 32 ký tự và 4 dấu gạch ngang “-”. Thông thường, các dấu gạch nối sẽ bị xóa khi chúng ta sử dụng. uuid.toString().replaceAll("-","").

Hiện tại có 5 phiên bản phương pháp tạo UUID, mỗi phiên bản có thuật toán khác nhau và phạm vi ứng dụng khác nhau.

  • UUID dựa trên thời gian - phiên bản 1: Điều này thường được tính toán thông qua thời gian hiện tại, số ngẫu nhiên và địa chỉ Mac cục bộ. org.apache.logging.log4j.core.utiltrong túi UuidUtil.getTimeBasedUuid()để sử dụng hoặc các công cụ khác trong gói. Vì địa chỉ MAC được sử dụng nên tính duy nhất có thể được đảm bảo, nhưng địa chỉ MAC cũng bị lộ và tính riêng tư không đủ tốt.
  • DCE Secure UUID - Phiên bản 2: UUID bảo mật DCE (Môi trường tính toán phân tán) có thuật toán tương tự như UUID dựa trên thời gian, nhưng 4 vị trí đầu tiên của dấu thời gian sẽ được thay thế bằng POSIX UID hoặc GID. Phiên bản UUID này hiếm khi được sử dụng trong thực tế.
  • UUID dựa trên tên (MD5) - phiên bản 3: UUID dựa trên tên có được bằng cách tính giá trị băm MD5 của tên và không gian tên. Phiên bản UUID này đảm bảo: tính duy nhất của các UUID được tạo với các tên khác nhau trong cùng một không gian tên; tính duy nhất của các UUID trong các không gian tên khác nhau và các UUID có cùng tên trong cùng một không gian tên được tạo nhiều lần đều giống nhau.
  • UUID ngẫu nhiên - Phiên bản 4: Tạo UUID dựa trên số ngẫu nhiên hoặc số giả ngẫu nhiên. Xác suất trùng lặp của UUID này có thể tính toán được nhưng khả năng trùng lặp là không đáng kể nên phiên bản này cũng là phiên bản được sử dụng thường xuyên. Đây là phiên bản được sử dụng trong JDK.
  • UUID dựa trên tên (SHA1) - phiên bản 5: Tương tự như thuật toán UUID dựa trên tên, ngoại trừ việc tính toán giá trị băm sử dụng thuật toán SHA1 (Thuật toán băm an toàn 1).

Phương thức tạo UUID đi kèm với JDK trong Java của chúng tôi là UUID được tạo dựa trên các số ngẫu nhiên trong phiên bản 4 và UUID dựa trên tên trong phiên bản 3. Nếu quan tâm, bạn có thể xem mã nguồn của nó.

public static void main(String[] args) { //Nhận UUID phiên bản 4 dựa trên một mảng byte ngẫu nhiên. UUID uuid = UUID.randomUUID(); System.out.println(uuid.toString().replaceAll("-", "")); //Nhận UUID phiên bản 3 (dựa trên tên) dựa trên mảng byte được chỉ định . byte[] nbyte = {10, 20, 30}; UUID uuidFromBytes = UUID.nameUUIDFromBytes(nbyte); System.out.println(uuidFromBytes.toString().replaceAll("-", ""));

lợi thế

  • Việc tạo ra rất đơn giản, việc tạo cục bộ không cần tiêu thụ mạng, hiệu suất rất cao và là duy nhất.

thiếu sót

  • Không có ý nghĩa kinh doanh cụ thể: chuỗi không có thứ tự, không có ý nghĩa kinh doanh cụ thể và không có xu hướng đặc điểm tự tăng
  • Mất an toàn thông tin: Thuật toán tạo UUID dựa trên địa chỉ MAC có thể khiến địa chỉ MAC bị rò rỉ và làm lộ vị trí của người dùng.
  • Hiệu suất lưu trữ kém và tốn thời gian truy vấn: Nếu được sử dụng làm khóa chính của cơ sở dữ liệu MySQL, trong công cụ InnoDB, sự rối loạn của UUID có thể gây ra những thay đổi thường xuyên về vị trí dữ liệu, ảnh hưởng nghiêm trọng đến hiệu suất. Bạn có thể tham khảo kiến ​​thức về nguyên tắc chỉ mục Mysql. cây B+.
  • Lượng dữ liệu được truyền lớn và không thể đọc được

2. ID tự động tăng dựa trên cơ sở dữ liệu

dựa trên cơ sở dữ liệuauto_incrementID tự tăng hoàn toàn có thể đóng vai tròID phân phối, cách triển khai cụ thể: cần có một phiên bản MySQL riêng để tạo ID và cấu trúc bảng như sau:

TẠO CƠ SỞ DỮ LIỆU `SEQ_ID`; TẠO BẢNG SEQID.SEQUENCE_ID ( id bigint(20) unsigned NOT NULL auto_increment, value char(10) NOT NULL default '', PRIMARY KEY (id), ); chèn vào SEQUENCE_ID(value) VALUES (' giá trị');

lợi thế

  • Triển khai đơn giản, ID tự động tăng đơn điệu và tốc độ truy vấn kiểu số nhanh

thiếu sót

  • Sự phụ thuộc mạnh mẽ vào DB, điểm duy nhất DB có nguy cơ ngừng hoạt động và không thể xử lý các tình huống tương tranh cao

3. Dựa trên chế độ cụm cơ sở dữ liệu

Như đã đề cập trước đó, phương pháp cơ sở dữ liệu một điểm không được khuyến khích. Sau đó, hãy thực hiện một số tối ưu hóa có tính sẵn sàng cao cho phương pháp trên và thay thế nó bằng cụm chế độ chủ-phụ. Nếu bạn sợ rằng một nút chính sẽ bị treo và không thể sử dụng được thì bạn có thể tạo cụm chế độ chính kép, tức là hai phiên bản Mysql có thể tạo ID tự tăng độc lập.

Khi đó sẽ xảy ra sự cố. ID tăng tự động của hai phiên bản MySQL bắt đầu từ 1.Tôi nên làm gì nếu ID trùng lặp được tạo ra?

giải pháp:cài đặtgiá trị bắt đầukích thước bước tự tăng

Cấu hình MySQL_1:

đặt @@auto_increment_offset = 1 -- giá trị bắt đầu được đặt @@auto_increment_increment = 2 -- kích thước bước

Cấu hình MySQL_2:

đặt @@auto_increment_offset = 2 -- giá trị bắt đầu được đặt @@auto_increment_increment = 2 -- kích thước bước

Theo cách này, ID tăng tự động của hai phiên bản MySQL là:

1, 3, 5, 7, 9
2, 4, 6, 8, 10

Vậy chúng ta nên làm gì nếu hiệu suất sau khi phân cụm vẫn không thể xử lý đồng thời cao? Cần phải mở rộng MySQL và thêm các nút, đây là một vấn đề rắc rối.

Các cụm cơ sở dữ liệu được mở rộng theo chiều ngang giúp giải quyết vấn đề áp lực một điểm trên cơ sở dữ liệu Đồng thời, đối với tính năng tạo ID, kích thước bước tăng tự động được đặt theo số lượng máy.

Thêm kênh thứ baMySQLCác phiên bản cần được sửa đổi thủ công cho một và hai phiên bản.Ví dụ MySQLGiá trị bắt đầu và kích thước bước củaID của máy thứ baVị trí sinh sản bắt đầu được đặt cao hơn vị trí hiện tạiID tăng tự động tối đaĐịa điểm thì xa hơn nhưng phải ở trạm thứ nhất hoặc thứ hai.Ví dụ MySQLID chưa tăng lênPhiên bản MySQL thứ bacủaID bắt đầugiá trị, nếu khôngID tự động tăngSẽ có sự lặp lạiNếu cần thiết có thể dừng lại và sửa đổi.

lợi thế

  • Giải quyết vấn đề điểm đơn DB

thiếu sót

  • Nó không có lợi cho việc mở rộng tiếp theo và trên thực tế, áp lực lên một cơ sở dữ liệu vẫn còn cao và nó vẫn không thể đáp ứng các tình huống đồng thời cao.

4. Chế độ phân đoạn số dựa trên cơ sở dữ liệu

Chế độ phân đoạn số là một trong những phương pháp triển khai chính của trình tạo ID phân tán hiện tại. Chế độ phân đoạn số có thể được hiểu là lấy ID tăng tự động từ cơ sở dữ liệu theo đợt và mỗi lần một phạm vi phân đoạn số được lấy ra khỏi cơ sở dữ liệu. , ví dụ (1,1000] đại diện cho 1000 Đối với mỗi ID, dịch vụ nghiệp vụ cụ thể sẽ tạo ID tăng tự động trong khoảng từ 1 đến 1000 và tải nó vào bộ nhớ. Cấu trúc bảng như sau:

TẠO BẢNG id_generator ( id int(10) NOT NULL, max_id bigint(20) NOT NULL COMMENT 'Id tối đa hiện tại', step int(20) NOT NULL COMMENT 'Độ dài của đoạn số', biz_type int(20) NOT NULL BÌNH LUẬN 'Loại doanh nghiệp', phiên bản int(20) KHÔNG BÌNH LUẬN NULL 'Số phiên bản', KHÓA CHÍNH (`id`) );

biz_type: đại diện cho các loại hình kinh doanh khác nhau

max_id: Id lớn nhất hiện có

bước: biểu thị độ dài của đoạn số

phiên bản: Đây là một khóa lạc quan Phiên bản được cập nhật mọi lúc để đảm bảo tính chính xác của dữ liệu trong quá trình đồng thời.

NHẬN DẠNG biz_type max_id bước chân phiên bản
1 101 1000 2000 0

Khi lô ID đoạn số này được sử dụng hết, hãy đăng ký lại đoạn số mới từ cơ sở dữ liệu.max_idtrường một lầncập nhậtvận hành,cập nhật max_id= max_id + bước, nếu cập nhật thành công, điều đó có nghĩa là lấy được phân đoạn số mới thành công và phạm vi phân đoạn số mới là(max_id ,max_id +bước]

cập nhật id_generator đặt max_id = #{max_id+step}, version = version + 1 trong đó version = # {version} và biz_type = XXX

Vì nhiều thiết bị đầu cuối kinh doanh có thể hoạt động cùng lúc nên số phiên bản được sử dụngphiên bảnCập nhật phương pháp khóa lạc quan, loại nàyID phân phốiPhương pháp tạo không phụ thuộc nhiều vào cơ sở dữ liệu và cơ sở dữ liệu sẽ không được truy cập thường xuyên, gây ít áp lực hơn cho cơ sở dữ liệu.

lợi thế

  • Cơ sở dữ liệu sẽ không được truy cập thường xuyên và áp lực lên cơ sở dữ liệu sẽ nhỏ.

thiếu sót

  • Cần phải lưu ID tự tăng của một đoạn số vào bộ nhớ, điều này làm tăng độ khó khi thực hiện.

5. Dựa trên chế độ Redis

Redis triển khai các ID duy nhất được phân phối chủ yếu bằng cách cung cấp các lệnh nguyên tử tự động tăng như INCR và INCRBY. Do đặc điểm đơn luồng của Redis, nó có thể đảm bảo rằng các ID được tạo chắc chắn là duy nhất và có thứ tự.

127.0.0.1:6379> set seq_id 1 // Khởi tạo ID tăng tự động thành 1 OK 127.0.0.1:6379> incr seq_id // Tăng 1 và trả về giá trị tăng (số nguyên) 2

Tuy nhiên, một máy duy nhất có những hạn chế về hiệu suất và không thể đáp ứng nhu cầu kinh doanh đồng thời cao, vì vậy nó có thể được triển khai trong một cụm. Phương pháp phân cụm sẽ liên quan đến các vấn đề tương tự như cụm cơ sở dữ liệu, do đó, nó cũng cần đặt phân đoạn và kích thước bước để đạt được điều đó.

Để tránh số lượng quá lớn sau khi tự tăng trong thời gian dài, nó có thể được sử dụng kết hợp với dấu thời gian hiện tại. Ngoài ra, để đảm bảo tính đồng thời và các vấn đề đa luồng trong kinh doanh, Redis + Lua có thể được sử dụng cho. mã hóa để đảm bảo an toàn.

lợi thế

  • Redis triển khai ID duy nhất toàn cầu được phân phối. Hiệu suất của nó tương đối cao và dữ liệu được tạo ra được sắp xếp theo thứ tự, điều này có lợi cho việc sắp xếp doanh nghiệp.

thiếu sót

  • Hệ thống cần giới thiệu các thành phần redis, điều này làm tăng độ phức tạp về cấu hình của hệ thống.

  • Khối lượng công việc cần thiết cho việc mã hóa và cấu hình tương đối lớn

  • Điểm lỗi duy nhất của Redis ảnh hưởng đến tính khả dụng của dịch vụ

  • sử dụnglàm lạiViệc thực hiện cần chú ý đến vấn đề kiên trì của redis.làm lạiCó hai phương pháp kiên trìRDBAOF

  • RDBẢnh chụp nhanh sẽ được chụp thường xuyên để duy trì. Nếu nó tiếp tục tăng nhưng.làm lạiNếu nó không được duy trì kịp thời, Redis sẽ bị treo. Sau khi khởi động lại Redis, việc sao chép ID sẽ xảy ra.

  • AOFMỗi lệnh ghi sẽ được duy trì ngay cả khiLàm lạiDù có bị treo máy cũng sẽ không có hiện tượng trùng lặp ID nhưng do tính đặc thù của lệnh incr sẽ gây raLàm lạiKhởi động lại để khôi phục dữ liệu mất quá nhiều thời gian.

6. Dựa trên chế độ thuật toán Snowflake (Snowflake)

Thuật toán Snowflake là thuật toán tạo ID được sử dụng bởi các dự án phân tán nội bộ của Twitter. Sau khi có nguồn mở, nó đã được các nhà sản xuất lớn trong nước khen ngợi rộng rãi. Dưới ảnh hưởng của thuật toán này, các công ty lớn đã liên tiếp phát triển các trình tạo ID phân tán với những đặc điểm riêng.

Bông tuyếtNhững gì được tạo ra là ID loại dài. Loại dài chiếm 8 byte và mỗi byte chiếm 8 bit. Nghĩa là, loại dài chiếm 64 bit.

Cấu trúc thành phần ID bông tuyết:chữ số dương(chiếm 1 chút) + Dấu thời gian(41 bit) + ID máy(chiếm 5 bit) + trung tâm dữ liệu(chiếm 5 bit) + giá trị tự gia tăng(12 bit), loại Dài bao gồm tổng cộng 64 bit.

  • Bit đầu tiên (1bit): Bit dài nhất trong Java là bit dấu, biểu thị số dương và số âm là 0 và số âm là 1. Nói chung, ID được tạo là số dương nên mặc định. là 0.
  • Phần dấu thời gian (41 bit): thời gian ở mức mili giây. Không nên lưu trữ dấu thời gian hiện tại. Thay vào đó, hãy sử dụng chênh lệch (dấu thời gian hiện tại - dấu thời gian bắt đầu cố định) để làm cho ID được tạo bắt đầu từ giá trị nhỏ hơn 41 bit. có thể sử dụng được 69 năm, (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69 năm
  • Id máy làm việc (10bit): còn gọi làID công việc, điều này có thể được cấu hình linh hoạt và mọi sự kết hợp giữa số phòng máy tính hoặc số máy đều được chấp nhận.
  • Phần số sê-ri (12bit), tự động tăng hỗ trợ cùng một nút có thể tạo 4096 ID trong cùng một mili giây

Theo logic của thuật toán này, bạn chỉ cần triển khai thuật toán này bằng ngôn ngữ Java và đóng gói nó dưới dạng một phương thức công cụ. Sau đó, mỗi ứng dụng doanh nghiệp có thể trực tiếp sử dụng phương thức công cụ này để lấy ID được phân phối. ứng dụng có công việc riêng của nó. ID máy là đủ và không cần phải xây dựng một ứng dụng riêng để lấy ID được phân phối.

Phiên bản JavaBông tuyếtTriển khai thuật toán

public class SnowflakeIdWorker { /** * 起始的时间戳,2020-01-01 00:00:00 */ private final static long START_TIMESTAMP = 1577808000000L; /** * 数据中心占用的位数 */ private final static long DATACENTER_ID_BIT = 5; /** * 工作机器标识占用的位数 */ private final static long WORKER_ID_BIT = 5; /** * 序列号占用的位数 */ private final static long SEQUENCE_BIT = 12; /** * 支持的数据中心最大值 */ private final static long MAX_DATACENTER_ID = ~(-1L << DATACENTER_ID_BIT); /** * 支持的工作机器标识最大值 */ private final static long MAX_WORKER_ID = ~(-1L << WORKER_ID_BIT); /** * 支持的序列号最大值 */ private final static long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT); /** * 工作机器标识向左移12位 */ private final static long WORKER_ID_LEFT = SEQUENCE_BIT; /** * 数据中心向左移(12+5)位 */ private final static long DATACENTER_ID_LEFT = SEQUENCE_BIT + WORKER_ID_BIT; /** * 时间戳向左移(12+5+5)位 */ private final static long TIMESTAMP_LEFT = DATACENTER_ID_LEFT + DATACENTER_ID_BIT; /** * 数据中心 */ private final long datacenterId; /** * 工作机器标识 */ private final long workerId; /** * 序列号 */ private long sequence = 0L; /** * 上一次时间戳 */ private long lastTimestamp = -1L; /** * 构造函数 * * @param datacenterId 数据中心 (0~31) * @param workerId 工作机器标识 (0~31) */ public SnowflakeIdWorker(long datacenterId, long workerId) { if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) { throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_ID or less than 0"); } if (workerId > MAX_WORKER_ID || workerId < 0) { throw new IllegalArgumentException("workerId can't be greater than MAX_WORKER_ID or less than 0"); } this.datacenterId = datacenterId; this.workerId = workerId; } /** * 获取下一个ID (该方法是线程安全的) * * @return long SnowflakeId */ public synchronized long nextId() { long currentTimestamp = currentTimeMillis(); //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 if (currentTimestamp < lastTimestamp) { throw new RuntimeException("Clock moved backwards. Refusing to generate id"); } //如果是同一时间生成的,则进行毫秒内序列 if (currentTimestamp == lastTimestamp) { //相同毫秒内,序列号自增 sequence = (sequence + 1) & MAX_SEQUENCE; //同一毫秒的序列数已经达到最大 if (sequence == 0L) { currentTimestamp = nextTimeMillis(); } } else { //不同毫秒内,序列号置为0 sequence = 0L; } //上次生成ID的时间戳 lastTimestamp = currentTimestamp; //移位并通过或运算拼到一起组成64位的ID //时间戳部分 return (currentTimestamp - START_TIMESTAMP) << TIMESTAMP_LEFT //数据中心部分 | datacenterId << DATACENTER_ID_LEFT //工作机器标识部分 | workerId << WORKER_ID_LEFT //序列号部分 | sequence; } /** * 阻塞到下一个毫秒,直到获得新的时间戳 * * @return 当前时间戳 */ private long nextTimeMillis() { long mill = currentTimeMillis(); while (mill <= lastTimestamp) { mill = currentTimeMillis(); } return mill; } /** * 返回以毫秒为单位的当前时间 * * @return 当前时间(毫秒) */ private long currentTimeMillis() { return System.currentTimeMillis(); } public static void main(String[] args) { SnowflakeIdWorker snowflake = new SnowflakeIdWorker(2, 3); for (int i = 0; i < (1 << 10); i++) { System.out.println(snowflake.nextId()); } } }

Thuật toán Snowflake cung cấp ý tưởng thiết kế tốt. ID được tạo bởi thuật toán Snowflake có xu hướng ngày càng tăng và không phụ thuộc vào các hệ thống của bên thứ ba như cơ sở dữ liệu. Nó được triển khai dưới dạng dịch vụ và có độ ổn định cao hơn. cũng rất cao và có thể rất linh hoạt trong việc phân bổ các bit theo đặc điểm kinh doanh riêng của mình.

Tuy nhiên, thuật toán Snowflake chủ yếu dựa vào đồng hồ của máy. Nếu đồng hồ trên máy bị đặt ngược lại, điều này sẽ khiến việc phát số lặp lại hoặc dịch vụ sẽ không khả dụng. Nếu một số ID tình cờ được tạo trước khi khôi phục và sau thời gian khôi phục thì các ID đã tạo có thể được lặp lại. Quan chức này không đưa ra giải pháp cho vấn đề này mà chỉ đơn giản đưa ra một lỗi, điều này sẽ khiến dịch vụ không khả dụng trong khoảng thời gian trước khi thời gian được phục hồi.

Nhiều thuật toán bông tuyết khác cũng được thiết kế dựa trên ý tưởng này và sau đó được cải tiến để tránh những thiếu sót của nó. Chế độ bông tuyết trong hệ thống tạo ID phân tán Baidu UidGenerator và Meituan Leaf được giới thiệu sau này đều được phát triển trên cơ sở bông tuyết.

lợi thế

  • Không phụ thuộc vào linh kiện bên ngoài, độ ổn định cao
  • Linh hoạt và thuận tiện, bạn có thể phân bổ bit theo đặc điểm kinh doanh của riêng mình
  • ID trên một máy tăng đơn điệu, với số mili giây ở vị trí cao và chuỗi tăng tự động ở vị trí thấp. Toàn bộ ID có xu hướng tăng dần.

thiếu sót

  • Phụ thuộc nhiều vào đồng hồ của máy Nếu đồng hồ trên máy bị chỉnh lùi sẽ gây ra tình trạng đánh số lặp lại hoặc dịch vụ sẽ không khả dụng.
  • ID có thể không được tăng lên trên toàn cầu. Nó tăng dần trên một máy, nhưng do môi trường phân tán, đồng hồ trên mỗi máy không thể được đồng bộ hóa hoàn toàn và đôi khi có thể có những tình huống trong đó nó không tăng dần trên toàn cầu.

7. Baidu (trình tạo uid)

trình tạo uidNó được phát triển bởi Phòng Công nghệ Baidu, địa chỉ GitHub của dự án là https://github.com/baidu/uid-generator

trình tạo uiddựa trênBông tuyếtThuật toán được triển khai và nguyên bảnbông tuyếtThuật toán khác ở chỗ,trình tạo uidHỗ trợ từXác định dấu thời gian,ID máy làm việcsố seri v.v. số chữ số trong mỗi phần vàtrình tạo uidDo người dùng xác địnhID công việcchiến lược thế hệ.

trình tạo uidNó cần được sử dụng cùng với cơ sở dữ liệu và cần thêm một cơ sở dữ liệu mới.CÔNG NHÂN_NODEbề mặt. Khi ứng dụng khởi động, một phần dữ liệu sẽ được chèn vào bảng cơ sở dữ liệu. ID tăng tự động được trả về sau khi chèn thành công là của máy.ID công việcDữ liệu bao gồm máy chủ và cổng.

trình tạo uid Cấu trúc thành phần ID:

ID công việc, chiếm 22 bit, thời gian chiếm 28 bit và tuần tự hóa chiếm 13 bit. Cần lưu ý rằng, và bản gốc.bông tuyếtKhông hoàn toàn giống nhau, đơn vị thời gian là giây chứ không phải mili giây.ID công việcNó cũng khác và cùng một ứng dụng sẽ tiêu thụ một ứng dụng mỗi khi khởi động lại.ID công việc.
Tài liệu tham khảo
https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

8. Meituan (Lá)

Lá câyĐược phát triển bởi Meituan, địa chỉ github: https://github.com/Meituan-Dianping/Leaf

Lá câyHỗ trợ cả chế độ phân đoạn số vàbông tuyếtChế độ thuật toán có thể được chuyển đổi.

Chế độ phân đoạn số

Đầu tiên hãy nhập mã nguồn https://github.com/Meituan-Dianping/Leaf rồi tạo bảnglá_alloc

DROP BẢNG NẾU Tồn tại `leaf_alloc`; TẠO BẢNG `leaf_alloc` ( `biz_tag` varchar(128) NOT NULL DEFAULT '' COMMENT 'Business key', `max_id` bigint(20) NOT NULL DEFAULT '1' COMMENT 'Hiện được phân bổ The id tối đa', `step` int(11) KHÔNG BÌNH LUẬN NULL 'Kích thước bước ban đầu, cũng là kích thước bước tối thiểu để điều chỉnh động', `description` varchar(256) DEFAULT NULL COMMENT 'Mô tả khóa nghiệp vụ', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Cập nhật thời gian cho bảo trì cơ sở dữ liệu' , PRIMARY KEY (`biz_tag`) ) ENGINE=InnoDB;

Sau đó kích hoạt nó trong dự ánChế độ phân đoạn số, định cấu hình thông tin cơ sở dữ liệu tương ứng và đóngbông tuyếtngười mẫu

leaf.name=com.sankuai.leaf.opensource.test leaf.segment.enable=true leaf.jdbc.url=jdbc:mysql://localhost:3306/leaf_test?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8 leaf.jdbc.username =root leaf.jdbc.password=gốc leaf.snowflake.enable=false #leaf.snowflake.zk.address= #leaf.snowflake.port=

khởi độngmáy chủ lá Mô-đun Ứng dụng máy chủ láDự án bắt đầu chạy

Chế độ phân đoạn số để lấy URL kiểm tra của ID tăng tự động được phân phối: http://localhost:8080/api/segment/get/leaf-segment-test

Chế độ phân đoạn số giám sát: http://localhost:8080/cache

mô hình bông tuyết

Lá câyMẫu bông tuyết dựa vàoNgười giữ vườn thú, khác vớibông tuyết nguyên bảnCác thuật toán, chủ yếu ởID công việcVề thế hệ củaLá câyở giữaID công việcdựa trênNgười giữ vườn thúID trình tự được tạo cho mỗi ứng dụng bằng cách sử dụngLá-bông tuyết, tất cả chúng sẽ ở đó khi bắt đầuNgười giữ vườn thúTạo ID trình tự, tương đương với một máy tương ứng với nút trình tự, nghĩa là mộtID công việc.

leaf.snowflake.enable=true leaf.snowflake.zk.address=127.0.0.1 leaf.snowflake.port=2181

Chế độ bông tuyết lấy url kiểm tra của ID tăng tự động được phân phối: http://localhost:8080/api/snowflake/get/test

9. Nhỏ bé

TinyidĐược phát triển bởi Didi, địa chỉ Github: https://github.com/didi/tinyid.

TinyidNó được thực hiện dựa trên nguyên tắc chế độ phân đoạn số vàLá câyHoàn toàn giống nhau, mỗi dịch vụ lấy một dãy số (1000,2000], (2000,3000], (3000,4000]

Tinyidcung cấphttpkhách hàng nhỏHai cách để truy cập

truy cập HTTP

(1) Nhập mã nguồn Tinyid:

bản sao git https://github.com/didi/tinyid.git

(2) Tạo bảng dữ liệu:

TẠO BẢNG `tiny_id_info` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Tự động tăng khóa chính', `biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT 'Loại hình kinh doanh, duy nhất', `begin_id` bigint (20 ) KHÔNG NULL MẶC ĐỊNH '0' BÌNH LUẬN 'Id bắt đầu, chỉ ghi giá trị ban đầu, không có ý nghĩa nào khác. Begin_id và max_id phải giống nhau trong quá trình khởi tạo', `max_id` bigint(20) NOT NULL DEFAULT '0' COMMENT 'Id tối đa hiện tại', `step` int( 11) MẶC ĐỊNH '0' BÌNH LUẬN 'kích thước bước', `delta` int(11) KHÔNG NULL MẶC ĐỊNH '1' BÌNH LUẬN 'mỗi lần tăng id', `phần còn lại` int(11) NOT NULL DEFAULT '0' COMMENT 'remainer', `create_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT 'create time', `update_time` timestamp NOT NULL DEFAULT '2010- 01-01 00:00:00' BÌNH LUẬN 'Thời gian cập nhật', `phiên bản` bigint(20) NOT NULL DEFAULT '0' COMMENT 'số phiên bản', PRIMARY KEY (`id`), UNIQUE KEY `uniq_biz_type` (`biz_type`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT 'bảng thông tin id '; TẠO BẢNG `tiny_id_token` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Id tăng tự động', `token` varchar(255) NOT NULL DEFAULT '' COMMENT 'token', `biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT 'Mã thông báo này là có thể truy cập Mã định danh loại doanh nghiệp', `remark` varchar(255) NOT NULL DEFAULT '' BÌNH LUẬN 'Ghi chú', `create_time` dấu thời gian KHÔNG NULL MẶC ĐỊNH '2010-01-01 00:00:00' BÌNH LUẬN 'Thời gian tạo', `update_time` dấu thời gian KHÔNG NULL MẶC ĐỊNH '2010-01-01 00:00:00' BÌNH LUẬN 'Thời gian cập nhật', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT 'bảng thông tin token'; CHÈN VÀO `tiny_id_info` (`id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time `, `update_time`, `version`) GIÁ TRỊ (1, 'test', 1, 1, 100000, 1, 0, '2018-07-21 23:52:58', '2018-07-22 23:19:27', 1); CHÈN VÀO `tiny_id_info` (` id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time`, `update_time`, `version`) GIÁ TRỊ (2, 'test_odd', 1, 1, 100000, 2, 1, '2018-07-21 23: 52:58', '2018-07-23 00:39:24', 3); CHÈN VÀO `tiny_id_token` (`id`, `token`, `biz_type`, `remark`, `create_time`, `update_time`) GIÁ TRỊ (1, '0f673adf80504e2eaa552f5d791b644c', 'test', '1', ' 2017-12-14 16:36:46', '2017-12-14 16:36:48'); CHÈN VÀO `tiny_id_token` (`id`, `token`, `biz_type`, `remark`, `create_time`, `update_time` ) GIÁ TRỊ (2, '0f673adf80504e2eaa552f5d791b644c', 'test_odd', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48');

(3) Cấu hình cơ sở dữ liệu:

datasource.tinyid.names=datasource chính.tinyid.primary.driver-class-name=com.mysql.jdbc.Driver datasource.tinyid.primary.url=jdbc:mysql://ip:port/databaseName?autoReconnect=true&useUnicode= true&characterEncoding=nguồn dữ liệu UTF-8.tinyid.primary.username=root datasource.tinyid.primary.password=123456

(4) Bắt đầumáy chủ nhỏbài kiểm tra

Nhận ID tăng tự động được phân phối: http://localhost:9999/tinyid/id/nextIdSimple?bizType=test&token=0f673adf80504e2eaa552f5d791b644c' Kết quả trả về: 3 Nhận ID tăng tự động được phân phối theo đợt: http://localhost:9999/tinyid/id/nextIdSimple?bizType=test&token=0f673adf80504e2eaa552f5d791b644c&batchSize=10' Kết quả trả về: 4,5,6,7,8,9,10,11,12,13
Truy cập máy khách Java

Lặp lại (2) (3) thao tác của phương thức Http

Giới thiệu các phụ thuộc

 com.xiaoju.uemc.tinyid tinyid-client ${tinyid.version 

Tệp cấu hình

tinyid.server =localhost:9999 tinyid.token =0f673adf80504e2eaa552f5d791b644c

Bài kiểm tra ,tinyid.tokenlà dữ liệu được chèn sẵn vào bảng cơ sở dữ liệu,Bài kiểm tra Là loại hình kinh doanh cụ thể,tinyid.tokenCho biết các loại hình kinh doanh có thể truy cập

// Nhận một ID tăng tự động được phân phối duy nhất Long id = TinyId.nextId("test"); // ID tăng tự động được phân phối hàng loạt theo yêu cầu Danh sách< Long > ids = TinyId.nextId("test", 10);

3. Tóm tắt

Bài viết này chỉ giới thiệu ngắn gọn về từng trình tạo ID phân tán, nhằm mục đích cung cấp cho bạn hướng học chi tiết. Mỗi phương pháp tạo ID đều có những ưu điểm và nhược điểm riêng. Cách sử dụng tùy thuộc vào nhu cầu cụ thể của doanh nghiệp.

31 4 0
Bài viết khuyến nghị: Ghi chú nghiên cứu chuyển giao phong cách
Bài viết khuyến nghị: Mô hình bộ nhớ Java
Bài viết khuyến nghị: LeetCode_Binary Tree_Simple_590.N Duyệt cây theo thứ tự sau
Bài viết khuyến nghị: 【arthas】Arthas Xem thông tin Mbean
người biết
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress