Redis Study Notes 1--Introduction (collection)

1. Introduction to Redis:

Redis (http://redis.io) is an open source, high-performance key-value store written in ANSI C. The project name of Redis is short for Remote Dictionary Server, but it is often referred to as a data structure server. Redis keys can include data types such as strings, hashes, lists, sets, and sorted sets. For these data types, you can perform atomic operations. For example: appending to strings; incrementing the value in a hash; adding elements to a list; computing the intersection, union, and difference of sets, etc.

In order to achieve excellent performance, Redis uses an in-memory dataset (dataset). Depending on the usage scenario, you can dump the dataset to disk at intervals to persist the data, or append each operation command to the end of the log.

Redis also supports master-slave replication, and has very fast non-blocking first synchronization (non-blocking first synchronization), automatic network reconnection and other functions. At the same time, Redis also has some other features, including a simple check-and-set mechanism, pub/sub and configuration settings, etc., in order to make Redis behave more like a cache (cache).

Redis also provides rich clients in order to support most of the popular programming languages ​​at this stage. 

2. Redis installation:

2.4.15 is currently the latest stable version. Download address: http://redis.googlecode.com/files/redis-2.4.15.tar.gz

Run the following command to install under linux (gcc is already installed on linux):

$ tar xzf redis-2.4.15.tar.gz
$ cd redis-2.4.15
$ make

After make, the compiled redis service program redis-server and the client program redis-cli for testing will appear in the redis-2.4.15/src directory.

Start the redis service below:

$./redis-server

Starting redis in this way uses the default configuration. You can also tell redis to use the specified configuration file to start with the following command through the startup parameter:

$./redis-server ../redis.conf

The redis.conf in the redis-2.4.15 directory is a default configuration file. We can use our own configuration files as needed.

After starting the redis service process, you can use the test client program redis-cli to interact with the redis service:

$ ./redis-cli
redis 127.0.0.1:6379
> set foo bar
OK
redis 127.0.0.1:6379
> get foo
"bar"

The above shows examples of get and set commands that operate on simple types of values. foo is the key and bar is a value of type string.

Stop Redis command:

./redis-cli-p 6379 shutdown      where 6379 is the port number of redis

3. Redis client:

There are many Redis clients, including C, C++, C#, Java, PHP, Perl, Python, Ruby, etc., which support most popular programming languages ​​at this stage. For details, please visit the redis official website: http://redis.io/ clients

The following is an example of a Redis client for Java:

Client jar package address https://github.com/xetorthio/jedis/downloads

package com.jd.redis.client;

 

import redis.clients.jedis.Jedis;

 

publicclass App {

    publicstaticvoid main(String[] args) {

        Jedis jr = null;

        try {

            //redis service address and port number

            jr = new Jedis("192.168.157.128" 6379);

            String key = "mkey";

            jr.set(key"helloredis!");

            String v = jr.get(key);

            String k2 = "count";

            jr.incr(k2);

            jr.incr(k2);

            System.out.println(v);

            System.out.println(jr.get(k2));

        catch (Exception e) {

            e.printStackTrace ();

        }

        finally{

            if(jr!=null){

                jr.disconnect();

            }

        }

    }

}

 

The Jedis client supports object pooling. You can obtain the Jedis client object from the pool through the JedisPool.getResource method, and release the Jedis object into the pool through the JedisPool.returnResource method. With the object pool, we can save a lot of time for reconnecting the recommended connection to the Redis Server. , the following is a performance comparison of not using the Jedis object pool and using the Jedis object pool:

Test method: Use the method of direct new Jedis and the method of obtaining Jedis objects from the pool, respectively, starting 200 concurrent cycles, and generating a concurrent loop 1000 times. Each concurrent thread uses a Jedis object.

The test code is as follows:

package com.jd.redis.client;

 

import java.util.concurrent.CountDownLatch;

 

import redis.clients.jedis.Jedis;

import  redis.clients.jedis.JedisPool;

import redis.clients.jedis.JedisPoolConfig;

 

publicclass JedisPoolTest {

 

    privatestatic JedisPoolConfigconfig;//Jedis客户端池配置

    privatestatic JedisPoolpool;//Jedis客户端池

   

    static{

        config =new JedisPoolConfig();

        config.setMaxActive(60000);

          config.setMaxIdle(1000);

          config.setMaxWait(10000);

          config.setTestOnBorrow(true);

          pool =new JedisPool(config,"192.168.157.128", 6380);

    }

   

    /**

     * 单笔测试(不用池)

     * @param count

     */

    publicstaticvoid testNoPool(int count){

        for(int i=0;i<count;i++){

            Jedis jr = null;

            try {

                jr = new Jedis("10.10.224.44", 6379);

                testOnce(jr);

            catch (Exception e) {

                e.printStackTrace();

            }

            finally{

                if(jr!=null)jr.disconnect();

            }

        }

    }

   

    /**

     * 单笔测试(用池)

     * @param count

     */

    publicstaticvoid testWithPool(int count){

        for(int i=0;i<count;i++){

            Jedis jr = null;

            try {

                jr = pool.getResource();

                testOnce(jr);

            catch (Exception e) {

                e.printStackTrace();

            }

            finally{

                if(jr!=null)pool.returnResource(jr);

            }

        }

    }

   

    /**

     * 并发测试(不用池)

     * @param paiallel并发量

     * @param count每个并发循环次数

     */

    publicstaticvoid paiallelTestNoPool(int paiallel, int count){

       

        Thread[] ts = new Thread[paiallel];

       

        //用该对象保证所线程都完成主线程才退出

        CountDownLatch cd = new CountDownLatch(paiallel);

       

        long start = System.currentTimeMillis();

        for(int i=0; i < paiallel; i++){

            ts[i] = new Thread(new WorkerNoPool(cd, count));

            ts[i].start();

        }

       

        try {

            cd.await();//等待所有子线程完成

        catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println("NoPool useTime:"+ (System.currentTimeMillis() - start));

    }

   

    /**

     * 并发测试(用池)

     * @param paiallel并发量

     * @param count每个并发循环次数

     */

    publicstaticvoid paiallelTestWithPool(int paiallel, int count){

       

        //用该对象保证所线程都完成主线程才退出

        CountDownLatch cd = new CountDownLatch(paiallel);

       

        long start = System.currentTimeMillis();

        Thread[] ts = new Thread[paiallel];

        for(int i=0; i < paiallel; i++){

            ts[i] = new Thread(new WorkerWithPool(cd, count));

            ts[i].start();

        }

        try {

            cd.await();//等待所有子线程完成

        catch (InterruptedException e) {

            e.printStackTrace();

        }

        System.out.println("Pool useTime:"+ (System.currentTimeMillis() - start));

        pool.destroy();

    }

   

    privatestaticvoid testOnce(Jedis jr){

        System.out.println(jr.incr("incrTest"));

    }

   

    publicstaticclass WorkerNoPoolimplements Runnable{

        private CountDownLatchcd;

        privateintcount;

       

        public WorkerNoPool(CountDownLatch cd,int count){

            this.cd = cd;

            this.count = count;

        }

       

        publicvoid run() {

            try {

                testNoPool(this.count);

            catch (Exception e) {

                e.printStackTrace();

            }

            finally{

                cd.countDown();

            }

        }

    }

   

    publicstaticclass WorkerWithPoolimplements Runnable{

       

        private CountDownLatchcd;

        privateintcount;

       

        public WorkerWithPool(CountDownLatch cd,int count){

            this.cd = cd;

            this.count = count;

        }

       

        publicvoid run() {

            try {

                testWithPool(this.count);

            catch (Exception e) {

                e.printStackTrace();

            }

            finally{

                cd.countDown();

            }

        }

    }

   

    publicstaticvoid main(String[] args) {

        paiallelTestNoPool(100, 1000);

        //paiallelTestWithPool(100, 1000);

    }

 

}

 

测试输出:

NoPool useTime:43863 //没用对象池的输出

Pool useTime:12101    //用了对象池的输出

从测试结果看没用对象池的时间要比用了对象池的时间多出31762毫秒,同时没有用对象池的还出现了很多超时情况,用了对象池的都成功了,运行10000次,我们姑且可以认为平均每次请求可以节约3.1762(31762/10000)毫秒连接时间。我用的是Win7中的Jedis Java客户端程序连接局域网的Linux虚拟机上的Redis Server。


各种客户端实际是对Redis Protocol的封装,方便我们使用,了解Redis Protocol后我们也可以自己实现客户端。

Redis Protocol详情请看:http://www.hoterran.info/redis_protocol

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325491228&siteId=291194637