Developing Redis applications with Redis C + + modules for ACL network communication libraries

Source: Internet
Author: User
Tags connection pooling php language new set redis cluster

I. Overview

(can skip this paragraph directly) Redis has become more and more widely used as a NoSQL data service, and its greatest advantage over memcached is that it provides a richer data structure, so the application scenario is broader. The advent of Redis is a boon for the vast majority of web application developers, while a large number of open source personnel contribute client-side code, such as the Java language of the jedis,php language Phpredis/predis, and so on, these languages of the Redis library is rich and useful, and the C + + programmer Seems to be not so fortunate, officially provided the C version of Hiredis as the client library, many enthusiasts are based on the Hiredis two times package and development form a C + + client library, but these libraries (including the official Hiredis) most of the use of trouble, to users caused a lot of error opportunities. Always wanted to develop a more user-friendly C + + version of the Redis client library (note: The officially provided library is basically protocol-based, which means that users need to spend a lot of time populating each protocol field and having to analyze different result types that the server might return), but every time you see a redis 150 When multiple client commands are in retreat, it is a huge development effort to provide an easy-to-use C + + function interface for each command.

In the subsequent development of several projects by the official Hiredis library repeatedly destroyed, finally can not endure, decided to re-develop a new set of Redis client API, the library not only to implement these 150 multiple client commands, but also need to provide convenient and flexible connection pool and connection pool cluster management functions (fortunately ACL Library already has a common network connection pool and connection pool Cluster Management module, in addition, according to the previous practice, it is possible to provide more than 150 function interfaces, because the same command may be due to different parameter type scenarios to provide multiple function interfaces (the final result is to provide 3, 400 function APIs); After a careful study of the Redis communication protocol, we started to design and develop (Redis protocol design is very simple and practical, that is, it can support binary, but also easy to manually debug). In the development process, a lot of reference to the Http://redisdoc.com website of the Chinese online translation version (very grateful to Huang classmate's hard work).

Ii. ACL Redis Library classification

According to the REDIS data structure type, divided into 12 large classes, each large class provides a different function interface, these 12 C + + classes are shown as follows:

1, Redis_key:redis all data types of the unified key operation class; Because REDIS data structure types are basic key-value types, where VALUE is divided into different data structure types;

2. Redis_connectioin: Classes related to Redis-server connection;

3. Redis_server: Classes related to redis-server service management;

4, the data type used in Redis_string:redis to denote the string;

5. The data type used to represent the hash table in Redis_hash:redis, each data object consists of "key-domain value pair set", that is, one KEY corresponds to multiple "domain value pairs", and each "domain value pair" consists of a field name and a field value;

6. The data type used to represent the list in Redis_list:redis;

7, the data type used in Redis_set:redis to denote the collection;

8. The data type used in Redis_zset:redis to denote an ordered set;

9. The data type used in Redis_pubsub:redis to denote "publish-subscribe";

10. The data types used in Redis_hyperloglog:redis to denote the hyperloglog cardinality estimation algorithm;

11. Data types used in Redis_script:redis to interact with LUA scripts;

12. The data type of multiple Redis commands that are executed in Redis_transaction:redis in a transactional manner (note: The transaction is very different from the transaction in the database, and the transaction process in Redis does not have a transaction rollback mechanism in the database. can only guarantee that many of these commands are executed or not executed);

In addition to the above 12 categories that correspond to the official Redis commands, several other classes are available in the ACL library:

13, Redis_command: The base class of the above 12 classes;

14, Redis_client:redis client network connection class;

15, Redis_result:redis command result class;

16, Redis_pool: For all the above commands to support the connection pool mode;

17, Redis_manager: For all of the above command allows to establish a connection pool cluster with multiple Redis-server services (that is, to establish a connection pool with each redis-server).

Iii. examples of ACL Redis use

1), here is a simple example of using the Redis client library in the ACL framework:

/** *  @param  conn {acl::redis_client&} redis  Connection objects  *  @return  { bool}  whether the operation process was successful  */bool test_redis_string (acl::redis_client& conn, const char*  key) {//  Create a command action class object of type  redis string , and bind the connection class object to the Action class//  object acl::redis_string  String_operation (&conn);const char* value =  "Test_value";//  add  K-V  value to  redis-server  if  (String_operation.set (key, value)  == false) {const acl:: Redis_result* res = string_operation.get_result ();p rintf ("Set key: %s error:  %s\r\n ", Key, res ? res->get_error ()  : " Unknown error ");return  false;} printf ("set key: %s ok!\r\n",  key);//  need to reset the state of the connection object, or call  conn.reset directly ()   You can also String_operation.reset ();//  to get the corresponding  key  values from  redis-server  acl::string buf;if   (string_operation.geT (key, buf)  == false) {const acl::redis_result* res = string_operation.get_ Result ();p rintf ("get key: %s error: %s\r\n", Key, res ? res->get_error ()  :  "Unknown error"); return false;} printf ("get key: %s ok, value: %s\r\n",  key, buf.c_str ());//  probe a given  key  is present in  redis-server , you need to create  redis   key//  class objects and will  redis  The connection object binds to the Acl::redis_key key_operation;conn.reset (); //  to reset the connection state key_operation.set_client (conn);   //  bind the Connection object to the Action object if  (Key_operation.exists (key)  == false) {if  (conn.eof ()) { printf ("disconnected from redis-server\r\n"); return false;} printf ("key: %s not exists\r\n",  key);} elseprintf ("key: %s exists\r\n",  key);//  Delete the specified  key  string class object Conn.reset ();  //   Reset Connection object Status if  (Key_operation.del (key, null) < 0) {printf ("del key: %s error\r\n",  key); return false;} elseprintf ("del key: %s ok\r\n",  key); return true;} /** *  @param  redis_addr {const char*} redis-server  server address, *    Format: Ip:port, such as:127.0.0.1:6379 *  @param  conn_timeout {int}  connection  redis-server   Time-out (seconds)  *  @param  rw_timeout {int}  communication with  redis-server   IO  Time-out (seconds)  */bool test_redis (const char* redis_addr, int conn_timeout, int  rw_timeout) {//  Create  redis  Client Network Connection class object Acl::redis_client conn (Redis_addr, conn_ timeout, rw_timeout);const char* key =  "Test_key"; Return test_redis_string (Conn,  key);}

The simple example above is to add the string type data to the Redis-server and get the specified string data from Redis-server, and determine whether the object specifying the specified key exists on the redis-server--- ; Removes the data object for the specified key from Redis-server (that is, the string object in the example). Using the simple example above, the user should be aware of the following points:

A), in the design of the Redis library in the ACL, the Redis connection class object is separated from the command operation class object, and the 12 redis command operation classes correspond to the corresponding 12 command operation classes in the ACL Redis library;

b), when using the Redis command to manipulate the class, the Redis connection class object and the command action class object must be bound (in order to facilitate the operation of the class inside the network connection, protocol package and Protocol resolution, etc.);

c), when reusing a Redis connection class object, you need to first reset the state of the connection class object (that is, call: Acl::redis_client::reset ()), which is primarily to free the intermediate memory resources of the last command operation process;

D), a Redis connection class object can be used by more than one command class operation class object (need to bind once before use);

e), there are two ways to bind a Redis connection object to a command operand: You can either pass in a non-empty Redis connection object in the constructor, or call the Set_client method of the action object to bind.

      2), a slight modification to the above example, so that it can support the connection pooling method, the sample code is as follows:

/** *  @param  conn {acl::redis_client&} redis  Connection objects  *  @return  { bool}  whether the operation process was successful  */bool test_redis_string (acl::redis_client& conn, const char*  key) The {...... //  code is the same as the above code, omitting return true;}   Sub-threading class Class test_thread : public acl::thread{public:test_thread (Acl::redis_pool & pool)  : pool_ (pool)  {}~test_thread ()  {}protected://  base class (ACL:: Thread) pure virtual function virtual void* run () {acl::string key;//  gives each thread a own  key so as to test, where  thread The _id ()//  function is a base class  acl::thread  method used to get the thread unique  ID  number Key.format ("Test_key: %lu",  THREAD_ID ());acl::redis_client* conn;for  (int i = 0; i < 1000;  i++) {//  Get a  redis  connection object from the  redis  Client connection pool conn =  (acl::redis_client*)  pool_.peek ();if  (conn == null) {printf ("Peek redis connectiOn error\r\n "); break;}   Perform  redis  client command operation Process if  (test_redis_string (*conn)  == false) {printf ("redis  Operation error\r\n "); break;}} Return null;} private:acl::redis_pool& pool_;}; Void test_redis_pool (Const char* redis_addr, int max_threads,int conn_timeout,  int rw_timeout) {//  Create  redis  Connect Pool object Acl::redis_pool pool (redis_addr, max_ Threads);//  Set the time-out and  IO  timeout for connection  redis , in seconds pool.set_timeout (conn_timeout, rw_ Timeout);//  Create a set of child threads std::vector<test_thread*> threads;for  (int i = 0;  i < max_threads; i++) {test_thread* thread = new test_thread (pool); Threads.push_back (thread); thread->set_detachable (false); Thread->start ();}   waits for all child threads to exit gracefully Std::vector<test_thread*>::iterator it = threads.begin ();for  (;  it != threads.end ();  ++it){(*it)->wait ();d elete  (*it);}} 

In addition to creating threads and Redis connection pools, the above example and Example 1 have the same code as the functionality.

3), below for example 2 above, make a slight modification, so that it can support the Redis cluster Connection pool way, the sample code is as follows:

/** *  @param  conn {acl::redis_client&} redis  Connection objects  *  @return  { bool}  whether the operation process was successful  */bool test_redis_string (acl::redis_client& conn, const char*  key) {......  //  the same as the above example code, omitting return true;}   Sub-threading class Class test_thread : public acl::thread{public:test_thread (Acl::redis_manager & manager)  : manager_ (manager)  {}~test_thread ()  {}protected://  base class (ACL:: Thread) pure virtual function virtual void* run () {acl::string key;//  gives each thread a own  key so as to test, where  thread The _id ()//  function is a base class  acl::thread  method used to get the thread unique  ID  number Key.format ("Test_key: %lu",  THREAD_ID ());acl::redis_pool* pool;acl::redis_client* conn;for  (int i = 0;  i < 1000; i++) {//  get an  redis-server  connection pool object from the connection pool cluster Manager pool =  (ACL:: redis_pool*)  manager_.peek ();if  (Pool == nulL) {printf ("peek connection pool failed\r\n"); break;}   Get a  redis  Connection object conn =  (acl::redis_client*)  pool_ from the  redis  client connection pool. Peek ();if  (conn == null) {printf ("peek redis connection error\r\n");   Perform  redis  client command operation Process if  (test_redis_string (*conn)  == false) {printf ("redis  Operation error\r\n "); break;}} Return null;} Private: (acl::redis_manager& manager_;}; Void test_redis_pool (Const char* redis_addr, int max_threads,int conn_timeout,  int rw_timeout) {//  Create  redis  Cluster Connection pool object Acl::redis_manager manager (Conn_timeout,  rw_timeout);//  Add multiple  redis-server  Server instance addresses Manager.set ("127.0.0.1:6379",  max_threads); Manager.set ("127.0.0.1:6380",  max_threads), Manager.set ("127.0.0.1:6381",  max_threads);//  set connection  redis  time-out and  IO  timeout, units are seconds pool.set_timeout (CONN_TIMEOUT,&NBsp;rw_timeout);//  Create a set of sub-threads std::vector<test_thread*> threads;for  (int i = 0 ;  i < max_threads; i++) {Test_thread* thread = new test_thread ( Manager); Threads.push_back (thread); thread->set_detachable (false); Thread->start ();}   waits for all child threads to exit gracefully Std::vector<test_thread*>::iterator it = threads.begin ();for  (;  it != threads.end ();  ++it) {(*it)->wait ();d elete  (*it);}}

This example modifies only a few pieces of code to support the cluster Redis connection pooling process by creating a cluster Connection pool object (which can add multiple Redis-server service addresses) and getting a connection pool object from the Cluster Connection pool object---> Gets a connection from the connection pool object---> The connection object is bound to the Redis action class object.

Iv. Summary

The above describes the use of new Redis libraries in the ACL framework and the process of processing, the library of complex protocols and network processing is hidden in the implementation of the internal, so that users feel like in the call of this function. The use of ACL threads is mentioned in Example 2, 3), and articles about using threads in more detail in the ACL library are described in: "Using the Acl_cpp Library to write multithreaded program."

SOURCE Download:

Domestic: Http://git.oschina.net/zsxxsz/acl/tree/master

http://sourceforge.net/projects/acl/

Svn:svn://svn.code.sf.net/p/acl/code/trunk

Github:https://github.com/zhengshuxin/acl

bbs:http://www.acl-dev.com/

QQ Group: 242722074


Developing Redis applications with Redis C + + modules for ACL network communication libraries

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.