Redis API trong Spica (1)

77 views
Skip to first unread message

pcdinh

unread,
Dec 24, 2009, 12:10:28 PM12/24/09
to The Spica Project
Chào mọi người,

Tôi vừa tái cấu trúc lại Redis API một chút nên giờ các lớp chính sẽ
nằm ở

http://code.google.com/p/spica/source/browse/trunk/library/spica/core/datasource/redis/Redis.php?spec=svn1560&r=1560

Rev mới nhất là 1560 có lẽ sẽ ổn định vị trí của các lớp này.

Sau đây là một số thông tin về cách thiết kế

Yêu cầu:

+ Không quá thủ tục như một số API khác như reditdotphp (thư viện PHP
ban đầu cho tác giả của Redis viết) hay PHPRedis (C extension)
+ Không thiên kiểu Zend như Rediska. Cấu trúc kiểu Zend ko tốt cho
performance và API kiểu Zend sẽ làm cho user xa lạ với cấu trúc
command gốc của Redis
+ Không chỉ hỗ trợ PHP 5.3 như Predis. Predis có điểm tôi không ưa là
nó hỗ trợ cluster ngay từ đầu và những ai không dùng cluster cũng sẽ
phải gánh overhead của việc xử lý cluster bên trong code. Thư viện
JRedis (java) họ tách cái này ra khiến cho logic từng mạch rõ ràng hơn
+ API ko quá nặng về design nhưng đủ trừu tượng để hỗ trợ DI,
consistent hashing, cluster về sau
+ Do Redis có đặc thù là hoạt động trên 1 database index nhất định cho
nên cần cần lưu ý là user có thể access nhiều db trên cùng một khối
mã. Phải thiết kế API làm sao cho việc việc switch đi lại giữa các db
được dễ dàng
+ Có thể phải tính đến bài toán non blocking khi xử lý batch

Để giảm IO và stat call, các lớp chính đặt trong Redis.php
Do số lượng command là lớn và ngày càng phình to cho nên đặt nó trong
Redis.php sẽ gây overhead khi có rất nhiều các câu command không dùng.
Vậy nên nó được tách ra
++ Database command gồm các câu liên quan đến server và db
++ Scalar command cho key value
++ List cho cấu trúc List
++ Set
++ SortSet

Thiết kế API
+ Khi user kết nối đến DB họ sẽ dùng 1 client. Trừu tượng hóa của nó
là lớp SpicaRedisClient
+ Client này kết nối đến 1 DB nhất định để theo tác dữ liệu trên đó.
Lời gọi là SpicaRedisClient::getConnection(). Connection trả về sẽ là
nơi gửi các request đến Redis server
+ Trước khi thực hiện lời gọi, chúng ta phải xây dựng 1 context, tức
là một ngữ cảnh môi trường kết nối với các thông số. Đó là
SpicaRedisContext. Context này sẽ truyền vào getConnection() để vận
hành cách kết nối.
+ 1 client có thể mở nhiều connection theo các context khác nhau. Các
connection là độc lập nhau
+ Các connection là blocking theo mặc định. Tôi đang tìm cách để xây
dựng API hỗ trợ non blocking vì nhiều khi cần asynchronous call.
+ Các connection có một phương thức là sendRequest với tham số là một
đối tượng thuộc interface SpicaRedisCommand. Các lớp thực hiện ràng
buộc này nằm trong các file Scalar.php, List.php ... và có đặc điểm
chung là có prefix: SpicaRedis sau đó là tên của command viết hoa toàn
bộ giống hệt Redis CLI. Mỗi command là một class cho phép định nghĩa
lại đặc tả và giao thức command mà không ảnh hưởng đến các lớp khác.
+ Phương thức sendRequest() sẽ trả về một SpicaRedisResponse, là lớp
hiểu giao thức Redis dựa trên text, giúp xử lý và trả về các dữ liệu
thân thiện user
+ 1 client có thể tạo ra nhiều connection độc lập đến các Redis server
và client tự quản lý lấy chu kỳ sống của chúng. Bạn gọi disconnect()
để đóng tất cả các connection đang mở.

Redis API trong Spica được thiết kế theo độ trừu tượng tăng dần và dựa
trên composition hơn là inheritance. Do vậy có thể phân chia các lớp
thành 2 dạng

+ Cấp cao SpicaRedisClient, SpicaRedisContext,
SpicaRedisDatabaseConnection
+ Cấp thấp (cấp protocol): SpicaRedisConnection, SpicaRedisResponse và
các command class

Về thiết kế các lớp cấp cao sử dụng các lớp cấp thấp để xử lý
communication cho theo bạn có thể hoàn toàn dùng trực tiếp các lớp cấp
thấp nếu muốn.

Cấp thấp

$conn = new SpicaRedisConnection('tcp://', $this->host, 6379);
$conn->open();
$conn->send('XXX'.SpicaRedisCommand::NL);
// in Redis 1.2: -ERR unknown command 'XXX'
// in Redis 1.1: -ERR unknown command
$resp = $conn->readLine();

Cấp cao

// Tạo ra một môi trường kết nối
$context = new SpicaRedisContext(0, $this->host);
// Dựng mô hình một client kết nối đến server
$client = new SpicaRedisClient();
// Tạo 1 kết nối với môi trường nêu trên
$conn = $client->getConnection($context);
// Gửi một command đến server để nhận về 1 response
$response = $conn->sendRequest(new SpicaRedisSET('k1',
'value1'));
// Phân tích response theo giao thức Redis
$this->assertTrue($response->getType() ===
SpicaRedisResponse::STATUS);

Tuy nhiên overhead của Redis API tren Spica là rất thấp nếu như các
bạn chú ý kỹ thuật thiết kế của tôi. Vì thế nên không ngại khi dùng
API cấp cao. Tạm thời các bạn xem các test case để biết thêm về cách
dùng các API này.

http://code.google.com/p/spica/source/browse/#svn/trunk/tests/datasource/redis

Hi vọng các giải đáp trên sẽ giúp các bạn làm quen với Redis API

pcdinh

tphuy

unread,
Dec 24, 2009, 1:29:41 PM12/24/09
to The Spica Project
@pcdinh: Em vừa tìm hiểu về spica ^^! và có một số thắc mắc sau:
1. Trong một bài anh đã viết trước đó có phần chuẩn viết mã. Việc sử
dụng camelCase mà ít sử dụng underscore là hợp lý. Nhưng theo em nên
hoàn toàn sử dụng camelCase thì code sẽ rõ ràng hơn nhiều. Em có xem
qua một số code anh viết thì thấy underscore vẫn còn sử dụng nhiều.
Việc sử dụng cả hai chuẩn đôi khi gây cho người lập trình viên cảm
giác rối (^^ đấy là theo ý em)
2. Anh có thể đưa ra roadmap cụ thể để chúng em có thể theo dõi một
cách sát sao hơn?
3. Các app mới có thừa kế từ app default được không ạ?
3. Tuần sau em có thời gian sẽ start viết thử một ứng dụng cho spica -
cms mạnh mẽ nhất :x

On Dec 25, 12:10 am, pcdinh <pcd...@gmail.com> wrote:
> Chào mọi người,
>
> Tôi vừa tái cấu trúc lại Redis API một chút nên giờ các lớp chính sẽ
> nằm ở
>

> http://code.google.com/p/spica/source/browse/trunk/library/spica/core...

> http://code.google.com/p/spica/source/browse/#svn/trunk/tests/datasou...

pcdinh

unread,
Dec 25, 2009, 1:10:54 AM12/25/09
to The Spica Project
Anh có quy ước về tên hàm

On 25 Tháng Mười Hai, 01:29, tphuy <huyt...@gmail.com> wrote:
> @pcdinh: Em vừa tìm hiểu về spica ^^! và có một số thắc mắc sau:
> 1. Trong một bài anh đã viết trước đó có phần chuẩn viết mã. Việc sử
> dụng camelCase mà ít sử dụng underscore là hợp lý. Nhưng theo em nên
> hoàn toàn sử dụng camelCase thì code sẽ rõ ràng hơn nhiều. Em có xem
> qua một số code anh viết thì thấy underscore vẫn còn sử dụng nhiều.
> Việc sử dụng cả hai chuẩn đôi khi gây cho người lập trình viên cảm
> giác rối (^^ đấy là theo ý em)


http://dev.wvb.com/spica/docs/guide/page/pname/code_standard

Giống như chuẩn viết mã của PHP (phần C), tên hàm theo quy ước
underscore và tên class/method/variable theo CamelCase

Hàm chủ yếu dùng ở 2 vị trí

+ ráp các thành phần của framework
+ trên template

Anh đang tính đến việc chuyển các thành phần ráp nối framework sang
OOP. Phần template vẫn dùng hàm vì việc mix HTML và OOP trông rối mắt.

> 2. Anh có thể đưa ra roadmap cụ thể để chúng em có thể theo dõi một
> cách sát sao hơn?

Đã có một roadmap từ lâu rồi (tháng 7) nhưng anh vẫn chưa thực hiện
xong. Em xong trong ML (phần giao diện web)

http://groups.google.com/group/spicaproject

> 3. Các app mới có thừa kế từ app default được không ạ?

Không. Anh ủng hộ composition hơn là inheritance. Về mặt triết lý thì
em có thể hiểu

+ Mỗi app là một lãnh địa riêng, không nhằm mục đích chia sẻ tài
nguyên mà mục đích là phân phối cho nên tính dependency là cần tính
đến.
+ Mỗi app chia thành nhiều module và có thể so sánh module với app của
Cake hay Zend. Vì thế app của Spica có độ sâu lớn hơn.
+ default app là ứng dụng demo.

Em xem trong thư mục tool có một số script để tạo khung ứng dụng.

> 3. Tuần sau em có thời gian sẽ start viết thử một ứng dụng cho spica -
> cms mạnh mẽ nhất :x

Anh sẽ hỗ trợ

pcdinh

Reply all
Reply to author
Forward
0 new messages