Thay thế cho get_posts () do sự cố bộ nhớ cache đa luồng


8

Tôi đang sử dụng pthreads để tạo nhiều chủ đề. Mỗi luồng trong một điểm cố gắng sử dụng get_posts()như sau:

$args = array(
    'post_type' => 'post',
    'post_status' => 'any'
);

$posts_list = get_posts($args);

Tuy nhiên, tôi kết thúc với sự cố sau đây:

HP Fatal error:  Call to a member function get() on a non-object in C:\dev\wordpress\wp-includes\cache.php on line 123

XIN LƯU Ý khi tôi thực hiện get_posts()cuộc gọi tương tự trong phần mã không được xâu chuỗi, tôi không gặp sự cố.

Bây giờ, câu hỏi của tôi, làm thế nào để gọi get_posts()từ trong một chủ đề pthread ? Và nếu tôi không thể làm điều đó, sự thay thế là gì?

Cảm ơn.


Cập nhật

Đây là mã mẫu

class My_Thread extends Thread {

    public function run() {

        /* DO SOME STUFF HERE */

        $args = array(
            'post_type' => 'post',
            'post_status' => 'any'
        );

        $posts_list = get_posts($args); // <------ This is causing the crash
    }
}

// Create a array
$threads = array();

//Iniciate Miltiple Thread
foreach ( range("A", "C") as $i ) {
    $threads[] = new My_Thread($i);
}

// Start The Threads
foreach ($threads as $thread) {
    $thread->start();
}

đó không phải là sự cố mà là lỗi ..... bạn nên sửa mã của mình để không xảy ra lỗi. Trong mọi trường hợp, các thư viện php không phải lúc nào cũng đa nhiệm an toàn, vì vậy vấn đề có thể là do một cái gì đó hoàn toàn khác.
Đánh dấu Kaplun

Để thêm vào, nếu có mã cần được bảo vệ để thực thi "cùng thời gian" hơn bạn cần sử dụng mutexes nhưng đó là cách thoát khỏi phạm vi ở đây.
Đánh dấu Kaplun

@MarkKaplun - Cảm ơn bạn đã đóng góp. Tuy nhiên, có vẻ như bạn đã bỏ lỡ điểm mà tôi nói rằng " khi tôi thực hiện get_posts()cuộc gọi tương tự trong phần mã không được xâu chuỗi, tôi không gặp sự cố "; vì vậy nó không phải là vấn đề với get_posts($args)cuộc gọi của tôi Hơn nữa, không có mã nào cần được bảo vệ tại thời điểm này, tôi chỉ đọc từ WordPress DB qua get_posts($args).
Greeso

3
@MarkKaplun - Có chuyện gì với bạn vậy? Tại sao bạn quá tiêu cực và hung hăng như vậy? Tại sao bạn cho rằng tôi không hiểu đa nhiệm và đề nghị rằng tôi không nên sử dụng pthreads? Ngay cả khi bạn đúng, chúng ta không nên thử những gì chúng ta không hiểu để mở rộng kiến ​​thức và giới hạn của mình? Và đây không phải là trang web về việc đặt câu hỏi nếu bạn không biết cách bạn làm một việc nhất định? Tôi không giả vờ bất cứ điều gì. Tôi đã gặp một lỗi, tôi nhận ra đó là do sử dụng pthreads và tôi đang yêu cầu một giải pháp, hoặc là một thiết lập hoặc một cách giải quyết lập trình. Tôi đã hy vọng cho một câu trả lời mang tính xây dựng từ chính bạn.
Greeso

2
Cho đến khi chúng tôi thực sự biết rằng WordPress không phải là lý do để phá vỡ mã này, thì đó là về chủ đề.
fuxia

Câu trả lời:


2

Vì có quá nhiều câu hỏi đối với câu hỏi, mặc dù các vấn đề về đa luồng quá rộng đối với định dạng của câu trả lời, tôi sẽ cố gắng giải thích lý do tại sao bạn không nên sử dụng API wordpress theo cách đa luồng ....

TL; DR - PHP không được coi là đa luồng đã sẵn sàng, vấn đề không phải là bản thân PHP mà chủ yếu là các thư viện mà nó sử dụng. Đây là lý do tại sao không nên sử dụng chế độ thực thi đa luồng trong apache mặc dù về lý thuyết, nó sẽ nhanh hơn một chút. Để thêm vào vấn đề lớp cơ bản không sẵn sàng đa luồng, lõi wordpress vi phạm yêu cầu cơ bản nhất của đa luồng - không có quyền truy cập miễn phí vào toàn cầu.

Vấn đề với toàn cầu trong môi trường đa luồng là gì? giả sử chúng ta có mã tìm kiếm ngây thơ

function inc() {
  global $g;

  $g++;
}

Mặc dù nó chỉ là một lớp lót, nhưng nó không phải là một hoạt động nguyên tử cho CPU và phải mất một số hướng dẫn cấp độ máy để thực hiện nó một cách chủ động. Cái gì đó như

move $g to register D
increment register D
move register D to $g

Bây giờ hãy giả sử rằng chúng ta có hai luồng AB gọi inc()"cùng một lúc" (rõ ràng chỉ có một CPU không có thứ gì giống nhau) và giá trị ban đầu của $ g là 0, giá trị của $ sẽ là bao nhiêu g sau khi cả hai chủ đề kết thúc? Nó sẽ phụ thuộc vào cách HĐH xử lý đa luồng, khi nào nó chuyển đổi giữa các luồng. Trong các HĐH kiểu "cũ", công việc của luồng phải khai báo bằng cách gọi API có thể lấy từ đó, nhưng điều đó dẫn đến nhiều vấn đề với các quy trình xử lý xấu khóa hệ thống trong HĐH "hiện đại" mà HĐH mất kiểm soát khi nào nó cảm thấy thích nó Trong cuộc sống thực, kết quả của mã sẽ là $ g sẽ có giá trị là 2, nhưng cũng có khả năng sau đây

Trong bối cảnh của A

move $g to register D
// value of D is 0
// OS stores the content of registers and switches to thread B
// B increments $g to 1 and finishes working
// OS restores content of registers to the context of thread A
// Value of register D is now 0
increment register D
move register D to $g

Kết quả cuối cùng là $ g có giá trị là 1.

Rõ ràng toàn cầu không phải là vấn đề duy nhất và xử lý đầu vào và đầu ra cũng là cốt lõi cho các vấn đề liên quan đến đọc sai.

Trong mã đa luồng thích hợp, bạn sử dụng khóa / mutex / semaphore / pipe / socket .... để tuần tự hóa quyền truy cập vào các tài nguyên toàn cầu đó để đảm bảo sẽ có kết quả dự đoán cho hoạt động. Wordpress không làm điều đó.

Địa ngục, wordpress thậm chí không phải là nhiều quá trình an toàn. Hầu hết thời gian nó bị loại bỏ vì lược đồ DB được xây dựng theo cách mà trong sử dụng thực tế ngăn không cần phải sửa đổi cùng một dữ liệu từ các quy trình khác nhau (các bài đăng khác nhau có các hàng khác nhau và không chia sẻ dữ liệu), nhưng hãy nhìn vào mã sidebar / widget và cố gắng tưởng tượng điều gì sẽ xảy ra nếu hai quản trị viên cố gắng thêm một widget khác cùng một lúc. Vì điều này sẽ yêu cầu thao tác của một tùy chọn cụ thể, kết quả cuối cùng có thể là cả hai vật dụng được thêm vào hoặc chỉ một trong số chúng.

Quay lại đa nhiệm. Trong unix, không giống như các cửa sổ, chi phí bổ sung để sinh ra một quy trình thay vì luồng là không đáng kể, do đó, việc sử dụng wp_remote_getmột số url đặc biệt để gọi thêm "luồng" là một điều rất hợp pháp để làm và tránh gần như tất cả các cạm bẫy liên quan đến đa luồng.


Điều này cũng được giải thích. Cảm ơn. Tôi cũng chỉ phát hiện ra rằng hỗ trợ cho pthread hoạt động với apache đang bị xóa. Để làm cho pthreads hoạt động, nó phải nằm trong phạm vi CLI . Đối với tôi, tôi cần pthreads , nhưng tôi sẽ hoãn giải pháp này cho đến sau khi phát hành (nghĩa là một sự nâng cao). Ngoài ra, tôi sẽ cần thiết lập WordPress dưới dạng một bản liệt kê CLI (chi tiết tại đây wp-cli.org ); làm như vậy sẽ cho phép tôi làm việc với môi trường pthreads / WordPress từ CLI, cho phép tôi thực hiện công việc nặng nhọc ở phần phụ trợ mà không bị apache. Lại một lần nữa.
Greeso

Chỉ cần thêm, tôi sẽ hạn chế pthread để xử lý các vấn đề không liên quan đến db. Và theo đề xuất của bạn, hãy sử dụng mutex cho db write.
Greeso

@Greeso, linux được thiết kế để sử dụng nhiều quy trình để xử lý các nhu cầu thực thi đồng thời, tạo ra một quy trình mới thực sự an toàn và nhanh như sử dụng pthreads ..
Mark Kaplun
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.