zoukankan      html  css  js  c++  java
  • Redis入门篇

    一、Redis简介:

            Redis(http://redis.io)是一款开源的、高性能的键-值存储(key-value store),它是用ANSI C来编写。Redis的项目名是Remote Dictionary Server的缩写,但它常被称作是一款数据结构服务器(data structureserver)。

            Redis的键值可以包括字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)和 有序集合(sorted sets)等数据类型。 对于这些数据类型,你可以执行原子操作。例如:对字符串进行附加操作(append);递增哈希中的值;向列表中增加元素;计算集合的交集、并集与差集等。

            为了获得优异的性能,Redis采用了内存中(in-memory)数据集(dataset)的方式。根据使用场景的不同,你可以每隔一段时间将数据集转存到磁盘上来持久化数据,或者在日志尾部追加每一条操作命令。

            Redis同样支持主从复制(master-slave replication),并且具有非常快速的非阻塞首次同步(non-blockingfirst synchronization)、网络断开自动重连等功能。同时Redis还具有其它一些特性,其中包括简单的check-and-set机制、pub/sub和配置设置等,以便使得Redis能够表现得更像缓存(cache)。

            Redis还提供了丰富的客户端,以便支持现阶段流行的大多数编程语言。 

    二、Redis安装:

    2.4.15目前是最新稳定版。下载地址:

    http://redis.googlecode.com/files/redis-2.4.15.tar.gz

    linux下运行如下命令进行安装(linux上已经安装好了gcc):

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

    make完后 redis-2.4.15/src目录下会出现编译后的redis服务程序redis-server,还有用于测试的客户端程序redis-cli。

    下面启动redis服务:

        $./redis-server

    这种方式启动redis 使用的是默认配置。也可以通过启动参数告诉redis使用指定配置文件使用下面命令启动:

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

    在redis-2.4.15目录下的redis.conf是一个默认的配置文件。我们可以根据需要使用自己的配置文件。

    启动redis服务进程后,就可以使用测试客户端程序redis-cli和redis服务交互了:

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

    上面演示了get和set命令操作简单类型value的例子。

    foo是key ,bar是个string类型的value。

    停止Redis命令:

        ./redis-cli-p 6379 shutdown     

    其中6379是redis的端口号。

    三、Redis客户端:

            Redis的客户端有很多,有C、C++、C#、Java、PHP、Perl、Python、Ruby等等,支持现阶段流行的大多数编程语言,详情请看redis官网:http://redis.io/clients

    下面是Java版的Redis客户端示例:

            客户端jar包地址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服务地址和端口号

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

                String key = "mkey";

                jr.set(key,"hello,redis!");

                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();

                }

            }

        }

    }


            Jedis客户端支持对象池,可以通过JedisPool.getResource方法从池中获取Jedis客户端对象,通过JedisPool.returnResource方法释放Jedis对象到池中,用对象池我们可以节省很多重新连接Redis Server的建议连接的时间。

            下面就是不用Jedis对象池与用Jedis对象池的一个性能对比:

            测试方法:分别用直接new Jedis和从池中获取Jedis对象的方法,起200个并发,生个并发循环1000次。每个并发线程用一个Jedis对象。

    测试代码如下:

    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

    原文链接:http://blog.csdn.net/freebird_lb/article/details/7733970

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法提高 P0404
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    Java实现 蓝桥杯VIP 算法训练 排列问题
    关于模态/非模态对话框不响应菜单的UPDATE_COMMAND_UI消息(对对WM_INITMENUPOPUP消息的处理)
  • 原文地址:https://www.cnblogs.com/peke/p/8044642.html
Copyright © 2011-2022 走看看