Linux 下 Redis使用介绍

出自http://blog.csdn.net/ajun_studio/article/details/6698147 和http://www.oschina.net/question/12_18065?sort=time

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类keyvalue存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP,Java客户端,使用很方便。
Redis使用单线程的IO复用模型,自己封装了一个简单的AeEvent事件处理框架,主要实现了epoll、kqueue和select,对于单纯只有IO操作来说,单线程可以将速度优势发挥到最大,但是Redis也提供了一些简单的计算功能,比如排序、聚合等,对于这些操作,单线程模型实际会严重影响整体吞吐量,CPU计算过程中,整个IO调度都是被阻塞住的。

Redis除了作为存储之外还提供了一些其它方面的功能,比如聚合计算、pubsub、scripting等,对于此类功能需要了解其实现原理,清楚地了解到它的局限性后,才能正确的使用,比如pubsub功能,这个实际是没有任何持久化支持的,消费方连接闪断或重连之间过来的消息是会全部丢失的,又比如聚合计算和scripting等功能受Redis单线程模型所限,是不可能达到很高的吞吐量的,需要谨慎使用。

本例子Linux采用的centOs5.4

下面来介绍一下redis的安装

  1. wget  http://redis.googlecode.com/files/redis-2.0.4.tar.gz  
  2. tar zxvf redis-2.0.4.tar.gz  
  3. cd  redis-2.0.4  
  4. make  

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

安装成功

启动服务

./redis-server

也可以通过启动参数告诉redis使用指定配置文件使用下面命令启动

./redis-server redis.conf

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

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

注意启动的时候,会出现

WARNING overcommit_memory is set to 0!Background save may fail under 

low memory condition. To fix this issue add'vm.overcommit_memory = 1' to /etc/sysctl.conf and 

[6020] 10 Aug 20:58:21 * The server is nowready to accept connections on port 6379

[6020] 10 Aug 20:58:21 - 0 clientsconnected (0 slaves), 533432 bytes in use

[6020] 10 Aug 20:58:30 - 0 clientsconnected (0 slaves), 533432 bytes in use

还有就是执行:sysctl vm.overcommit_memory=1

关于redis一些资料的学习可以到http://www.cnblogs.com/xhan/archive/2011/02/08/1949867.html去学习 ,很全面

下面介绍一个简单java客户端Jedis,大家可以到https://github.com/xetorthio/jedis这网址下载


redis作为NoSQL数据库的一种应用,响应速度和命中率上还是比较高效的。项目中需要用集中式可横向扩展的缓存框架,做了一点调研,即便redis、memcached存在效率上的差异(具体比较参考http://timyang.net/data/mcdb-tt-redis/),但其实都能满足目前项目的需求;但是redis还是比较风骚的,支持链表和集合操作,支持正则表达式查找key,目前项目缓存的结果大多是链表,如果链表新增或者修改数据的话,redis就体现出了极大的优势(memcached只能重新加载链表,redis可以对链表新增或者修改)

1:下载redis
下载地址 http://code.google.com/p/redis/downloads/list
推荐下载redis-1.2.6.tar.gz,之前这个版本同事已经有成功安装运行的经验,redis-2.0.4.tar.gz 这个版本我安装后无法操作缓存数据,具体原因后续再说

2:安装redis
下载后解压 tar zxvf redis-1.2.6.tar.gz 到任意目录,例如/usr/local/redis-1.2.6

解压后,进入redis目录
    cd /usr/local/redis-1.2.6 
    make 

拷贝文件
cp redis.conf /etc/ 这个文件时redis启动的配置文件
cp redis-benchmark redis-cli redis-server /usr/bin/ #这个倒是很有用,这样就不用再执行时加上./了,而且可以在任何地方执行

设置内存分配策略(可选,根据服务器的实际情况进行设置)
/proc/sys/vm/overcommit_memory
可选值:0、1、2。
0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2, 表示内核允许分配超过所有物理内存和交换空间总和的内存

值得注意的一点是,redis在dump数据的时候,会fork出一个子进程,理论上child进程所占用的内存和parent是一样的,比如parent占用的内存为8G,这个时候也要同样分配8G的内存给child,如果内存无法负担,往往会造成redis服务器的down机或者IO负载过高,效率下降。所以这里比较优化的内存分配策略应该设置为 1(表示内核允许分配所有的物理内存,而不管当前的内存状态如何)

开启redis端口,修改防火墙配置文件
    vi /etc/sysconfig/iptables 

加入端口配置
    -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT 

重新加载规则
    service iptables restart  

3:启动redis服务
    [root@Architect redis-1.2.6]# pwd 
    /usr/local/redis-1.2.6 
    [root@Architect redis-1.2.6]# redis-server /etc/redis.conf 

查看进程,确认redis已经启动

    [root@Architect redis-1.2.6]# ps -ef | grep redis 
    root       401 29222  0 18:06 pts/3    00:00:00 grep redis 
    root     29258     1  0 16:23 ?        00:00:00 redis-server /etc/redis.conf 

如果这里启动redis服务失败,一般情况下是因为redis.conf文件有问题,建议检查或找个可用的配置文件进行覆盖,避免少走弯路,这里建议,修改redis.conf,设置redis进程为后台守护进程

    # By default Redis does not run as a daemon. Use 'yes' if you need it. 
    # Note that Redis will write a pid file in /var/run/redis.pid when daemonized. 
    daemonize yes 

4:测试redis
    [root@Architect redis-1.2.6]# redis-cli 
    redis> set name songbin 
    OK 
    redis> get name  
    "songbin" 

5:关闭redis服务
    redis-cli shutdown 

redis服务关闭后,缓存数据会自动dump到硬盘上,硬盘地址为redis.conf中的配置项dbfilename dump.rdb所设定
强制备份数据到磁盘,使用如下命令

    redis-cli save 或者 redis-cli -p 6380 save(指定端口)



安装的时候,make完了之后再make install 就自动安装到/usr/local/bin下了,不用手动cp的





这里给大家提供一个简单的对jedis的封装类以供参考

Redis.java

  1. package com.ajun.redis;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5. import java.util.Set;  
  6. import java.util.TreeSet;  
  7.   
  8. import redis.clients.jedis.Jedis;  
  9. import redis.clients.jedis.JedisPool;  
  10. import redis.clients.jedis.JedisPoolConfig;  
  11. /** 
  12.  *  
  13.  * @author ajun 
  14.  * 
  15.  */  
  16. public class Redis {  
  17.     private static JedisPool pool;  
  18.     private static int DBIndex=1;  
  19.     private static String host="192.168.1.200";  
  20.     private static int port=6379;  
  21.     private static int timeout=60*1000;  
  22.     static {  
  23.         JedisPoolConfig config = new JedisPoolConfig();  
  24.         config.setMaxActive(100);  
  25.         config.setMaxIdle(20);  
  26.         config.setMaxWait((long)1000);        
  27.         config.setTestOnBorrow(false);            
  28.         pool = new JedisPool(config, host, port, timeout);//线程数量限制,IP地址,端口,超时时间           
  29.           
  30.     }  
  31.       
  32.       
  33.     /** 
  34.      *  注意: 
  35.      *  作为一个key value存在,很多开发者自然的使用set/get方式来使用Redis,实际上这并不是最优化的使用方法。 
  36.      *  尤其在未启用VM情况下,Redis全部数据需要放入内存,节约内存尤其重要。 
  37.         假如一个key-value单元需要最小占用512字节,即使只存一个字节也占了512字节。 
  38.         这时候就有一个设计模式,可以把key复用,几个key-value放入一个key中,value再作为一个set存入, 
  39.         这样同样512字节就会存放10-100倍的容量。 
  40.         用于存储多个key-value的值,比如可以存储好多的person Object 
  41.         例子:>redis-cli 
  42.         存储:redis 127.0.0.1:6379> hset personhash personId personObject 
  43.         获得:redis 127.0.0.1:6379> hget personhash personId (就可以获得当前personId对应的person对象) 
  44.      * @param key hashset key 
  45.      * @param field 相当于personId 
  46.      * @param value  person Object 
  47.      */  
  48.     public static void hsetItem(String key,String field,byte [] value){  
  49.         Jedis jedis=null;  
  50.         try {  
  51.             jedis = pool.getResource();  
  52.             jedis.connect();  
  53.             jedis.select(DBIndex);  
  54.             jedis.hset(key.getBytes(), field.getBytes(), value);  
  55.         } catch (Exception e) {  
  56.             e.printStackTrace();  
  57.         }finally{  
  58.             if(jedis!=null)  
  59.                 pool.returnResource(jedis);  
  60.         }  
  61.     }  
  62.       
  63.     public static byte []  hgetItem(String key,String field){  
  64.         Jedis jedis=null;  
  65.         byte [] value = null;  
  66.         try {  
  67.             jedis = pool.getResource();  
  68.             jedis.connect();  
  69.             jedis.select(DBIndex);  
  70.             value= jedis.hget(key.getBytes(), field.getBytes());  
  71.             //jedis.hgetAll(key);  
  72.         } catch (Exception e) {  
  73.             e.printStackTrace();  
  74.         }finally{  
  75.             if(jedis!=null)  
  76.                 pool.returnResource(jedis);  
  77.         }  
  78.         return value;  
  79.     }  
  80.       
  81.     /** 
  82.      * @param key 
  83.      * @param value 
  84.      * @param seconds 有效时间 秒为单位 0为永久有效 
  85.      */  
  86.     public static void setItem(String key ,byte [] value,int seconds){  
  87.         Jedis jedis=null;  
  88.         try {  
  89.             jedis = pool.getResource();  
  90.             jedis.connect();  
  91.             jedis.select(DBIndex);  
  92.             if(seconds==0){  
  93.                 jedis.set(key.getBytes(), value);  
  94.             }else{  
  95.                 jedis.setex(key.getBytes(), seconds, value);  
  96.             }  
  97.               
  98.         } catch (Exception e) {  
  99.             e.printStackTrace();  
  100.         }finally{  
  101.             if(jedis!=null)  
  102.                 pool.returnResource(jedis);  
  103.         }  
  104.     }  
  105.       
  106.       
  107.       
  108.       
  109.     /** 
  110.      * 删除 
  111.      * @param keys 
  112.      */  
  113.     public static void del(String... keys){  
  114.         Jedis jedis=null;  
  115.         if(keys!=null){  
  116.             try {  
  117.                 jedis = pool.getResource();  
  118.                 jedis.connect();  
  119.                 jedis.select(DBIndex);  
  120.                 jedis.del(keys);  
  121.             } catch (Exception e) {  
  122.                 e.printStackTrace();  
  123.             }finally{  
  124.                 if(jedis!=null)  
  125.                     pool.returnResource(jedis);  
  126.             }  
  127.         }  
  128.     }  
  129.       
  130.   
  131.       
  132.     /** 
  133.      * 头部添加元素 
  134.      * @param key 
  135.      * @param value 
  136.      */  
  137.     public static void lpushToList(String key,byte[] value){  
  138.         Jedis jedis=null;  
  139.         try {  
  140.             jedis = pool.getResource();  
  141.             jedis.connect();  
  142.             jedis.select(DBIndex);  
  143.             jedis.lpush(key.getBytes(), value);   
  144.               
  145.         } catch (Exception e) {  
  146.             e.printStackTrace();  
  147.         }  
  148.         finally{  
  149.             if(jedis!=null)  
  150.             pool.returnResource(jedis);  
  151.         }  
  152.     }  
  153.       
  154.     /** 
  155.      * 返回List 
  156.      * @param key 
  157.      * @param value 
  158.      */  
  159.     public static List<byte[]>  lrangeFromList(String key,int start ,int end){  
  160.         Jedis jedis=null;  
  161.         List<byte[]> list = null;  
  162.         try {  
  163.             jedis = pool.getResource();  
  164.             jedis.connect();  
  165.             jedis.select(DBIndex);  
  166.             list = jedis.lrange(key.getBytes(), start, end);  
  167.               
  168.         } catch (Exception e) {  
  169.             e.printStackTrace();  
  170.         }  
  171.         finally{  
  172.             if(jedis!=null)  
  173.             pool.returnResource(jedis);  
  174.         }  
  175.         return list;  
  176.     }  
  177.       
  178.     /** 
  179.      *  
  180.      * @param key key 
  181.      * @param member 存储的value 
  182.      * @param score 排序字段 一般为objecId 
  183.      */  
  184.     public static void addItemToSortSet(String key,byte[] member,double score){  
  185.         Jedis jedis=null;  
  186.         try {  
  187.             jedis = pool.getResource();  
  188.             jedis.connect();  
  189.             jedis.select(DBIndex);  
  190.             jedis.zadd(key.getBytes(), score, member);  
  191.         } catch (Exception e) {  
  192.             e.printStackTrace();  
  193.         }finally{  
  194.             if(jedis!=null)  
  195.                 pool.returnResource(jedis);  
  196.         }  
  197.     }  
  198.       
  199.     public static void addListToSortSet(String key,List<byte[]> list,List<Double> scores){  
  200.         Jedis jedis=null;  
  201.         try {  
  202.             jedis = pool.getResource();  
  203.             jedis.connect();  
  204.             jedis.select(DBIndex);  
  205.             if(list!=null&& !list.isEmpty()&& scores!=null&& !scores.isEmpty() && list.size()==scores.size()){  
  206.                 for(int i=0;i<list.size();i++){  
  207.                     jedis.zadd(key.getBytes(), scores.get(i), list.get(i));  
  208.                 }  
  209.             }  
  210.         } catch (Exception e) {  
  211.             e.printStackTrace();  
  212.         }finally{  
  213.             if(jedis!=null)  
  214.                 pool.returnResource(jedis);  
  215.         }  
  216.     }  
  217.       
  218.     public static List<byte[]> getFromSortSet(String key,int start ,int end,OrderStatus orderStatus){  
  219.         Jedis jedis=null;  
  220.         List<byte[]> list = new ArrayList<byte[]>();  
  221.         Set<byte[]> set= new TreeSet<byte[]>();  
  222.         try {  
  223.             jedis = pool.getResource();  
  224.             jedis.connect();  
  225.             jedis.select(DBIndex);  
  226.             if(orderStatus.equals(OrderStatus.DESC)){  
  227.                 set = jedis.zrevrange(key.getBytes(), start, end);  
  228.             }else{  
  229.                 set = jedis.zrange(key.getBytes(), start, end);  
  230.             }  
  231.             if(set!=null && !set.isEmpty()){  
  232.                 for(byte[] b:set){  
  233.                     list.add(b);  
  234.                 }  
  235.             }  
  236.         } catch (Exception e) {  
  237.             e.printStackTrace();  
  238.         }finally{  
  239.             if(jedis!=null)  
  240.                 pool.returnResource(jedis);  
  241.         }  
  242.         return list;  
  243.     }  
  244.   
  245.     public static byte[] getItem(String key)  
  246.     {  
  247.         Jedis jedis=null;  
  248.         byte[] s=null;  
  249.         try {  
  250.             jedis = pool.getResource();  
  251.             jedis.select(DBIndex);  
  252.             s = jedis.get(key.getBytes());  
  253.             return s;  
  254.         } catch (Exception e) {  
  255.             e.printStackTrace();  
  256.             return s;  
  257.         }     
  258.         finally{  
  259.             if(jedis!=null)  
  260.             pool.returnResource(jedis);  
  261.               
  262.         }  
  263.           
  264.           
  265.     }  
  266.       
  267.     public static void delItem(String key)  
  268.     {  
  269.         Jedis jedis=null;  
  270.         try {  
  271.             jedis = pool.getResource();           
  272.             jedis.select(DBIndex);            
  273.             jedis.del(key.getBytes());  
  274.           
  275.         } catch (Exception e) {  
  276.             e.printStackTrace();  
  277.         }  
  278.         finally{  
  279.             if(jedis!=null)  
  280.             pool.returnResource(jedis);  
  281.         }  
  282.           
  283.     }  
  284.     public static long getIncrement(String key)  
  285.     {  
  286.         Jedis jedis=null;  
  287.         try {  
  288.             jedis = pool.getResource();           
  289.             jedis.select(DBIndex);            
  290.             return jedis.incr(key);  
  291.           
  292.         } catch (Exception e) {  
  293.             e.printStackTrace();  
  294.             return 0L;  
  295.         }  
  296.         finally{  
  297.             if(jedis!=null)  
  298.             pool.returnResource(jedis);  
  299.         }  
  300.           
  301.     }  
  302.       
  303.     public static void getkeys(String pattern){  
  304.           
  305.         Jedis jedis=null;  
  306.         try {  
  307.             jedis = pool.getResource();           
  308.             jedis.select(DBIndex);    
  309.             Set<String> keys = jedis.keys(pattern);  
  310.             for(String b:keys){  
  311.                 System.out.println("keys==> "+b);  
  312.                   
  313.             }  
  314.           
  315.         } catch (Exception e) {  
  316.             e.printStackTrace();  
  317.         }  
  318.         finally{  
  319.             if(jedis!=null)  
  320.             pool.returnResource(jedis);  
  321.         }  
  322.           
  323.     }  
  324.   



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值