Kendynet constructs an asynchronous redis access service, kendynetredis
Recently, I started to develop a mobile game server on kendynet. The game type is survival challenge. The data structure and type to be stored are relatively simple. So I chose redis for storage, it is sufficient to use string for data types. So I wrote a simple redis asynchronous access interface on kendynet.
Design Concept
1. The project is time-consuming. Instead of providing a large and comprehensive access interface, only one request interface is provided to send redis requests.
2. In redis, keys and values are both stored as strings. the user is responsible for serializing the data into strings and deserializing the data back from the string.
3. The Service supports local access and remote access. The service automatically returns the result to the requester Based on the location where the request is initiated.
4. The database operation result is returned to the caller through an asynchronous message.
Example
The following is an example:
# Include <stdio. h> # include <stdlib. h> # include "core/msgdisp. h "# include <stdint. h> # include "testcommon. h "# include" core/db/asyndb. h "asyndb_t asydb; int g = 0; int count = 0; void db_setcallback (struct db_result * result); void db_getcallback (struct db_result * result) {// printf ("% s \ n", result-> result_str); count ++; char req [256]; snprintf (req, 256, "set key % d", g, g); if (0! = Asydb-> request (asydb, new_dbrequest (db_set, req, db_setcallback, result-> ud, make_by_msgdisp (msgdisp_t) result-> ud )))) printf ("request error \ n");} void db_setcallback (struct db_result * result) {if (result-> ud = NULL) printf ("error \ n "); char req [256]; snprintf (req, 256, "get key % d", g); g = (g + 1) % 102400; asydb-> request (asydb, new_dbrequest (db_get, req, db_getcallback, result-> ud, make_by_msgdisp (msgdisp_t) result-> ud );} Int32_t asynprocesspacket (msgdisp_t disp, msgsender sender, rpacket_t rpk) {uint16_t cmd = encrypt (rpk); if (cmd = CMD_DB_RESULT) {struct db_result * result = rpk_read_dbresult (rpk); result-> callback (result); free_dbresult (result);} return 1;} static void * service_main (void * ud) {msgdisp_t disp = (msgdisp_t) ud; while (! Stop) {msg_loop (disp, 50);} return NULL;} int main (int argc, char ** argv) {setup_signal_handler (); msgdisp_t disp1 = new_msgdisp (NULL, NULL, NULL, NULL, asynprocesspacket, NULL); thread_t service1 = create_thread (THREAD_JOINABLE); msgdisp_t disp2 = new_msgdisp (NULL, asynprocesspacket, NULL ); thread_t service2 = create_thread (THREAD_JOINABLE); asydb = new_asyndb (); asydb-> connectdb (asydb, "127. 0.0.1 ", 6379); asydb-> connectdb (asydb," 127.0.0.1 ", 6379); // send the first request uuchar req [256]; snprintf (req, 256, "set key % d", g, g); asydb-> request (asydb, new_dbrequest (db_set, req, db_setcallback, disp1, make_by_msgdisp (disp1 ))); thread_start_run (service1, service_main, (void *) disp1); asydb-> request (asydb, new_dbrequest (db_set, req, db_setcallback, disp2, make_by_msgdisp (disp2 ))); thread_start_run (service2, service_main, (void *) Disp2); uint32_t tick, now; tick = now = GetSystemMs (); while (! Stop) {sleepms (100); now = GetSystemMs (); if (now-tick> 1000) {printf ("count: % d \ n", count ); tick = now; count = 0 ;}} thread_join (service1); thread_join (service2); return 0 ;}
The above example creates a redis asynchronous processor and establishes two connections to the same redis server. in implementation, each connection creates a working thread to complete database requests. these worker threads share a task queue. User-sent requests are shipped to the task queue for extraction and execution by the worker threads.
Create two message splitters and two threads, then initiate two set requests and start the message splitters thread.
After the set is returned, the message splitter calls back db_setcallback and continues to initiate a get request in db_setcallback,
In the get callback db_getcallback, the new set request is initiated again and again.