Redis 学习笔记

阅读更多
一、为什么要选择redis
   1)性能好:采用缓存性能会比数据库好很多。
   2)可扩展:采用缓存可以很容易扩展,能够通过增加节点来扩展容量和性能,这在解决大流量,高并发的网站性能时是非常关键的。
   3)丰富的存储结构:如果只有以上两点,那么跟memcached也没什么区别,相比memcached,redis可以存储MAP,SET,LIST等集合类型,在处理复杂数据时,能够提升性能。
   4)可持久化:redis提供了两种持久化机制 AOP和RDB。
   5)主备:支持1个master n个slave的模式,同步性能非常好。
   6)集群:在redis3.x版本中,已经全面支持集群功能。当master失效之后,Sentinel会自动从slave中选举一个成为master。
   7)客户端工具支持:有良好的客户端工具,可以实时查看缓存中的数据,检测缓存的运行情况。
二、redis安装篇
   1)windows版
      下载地址: https://github.com/MSOpenTech/redis/releases/download/win-2.8.2104/Redis-x64-2.8.2104.zip
      下载解压就可以了。
      服务端启动命令: redis-server.exe redis.windows.conf
     客户端链接命令: redis-cli.exe -h localhost -p 6379
   2)linux版
      下载地址: http://download.redis.io/releases/redis-3.0.4.tar.gz
     (1)下载后解压 tar -xvf redis-3.0.4.tar.gz
     (2)然后切换到src目录(redis-3.0.4/src),输入命令:make && makeinstall
        如果报错 error: jemalloc/jemalloc.h: No such file or directory
        解决方法 make MALLOC=libc
     (3)新建一个目录bin作为运行目录,在编译完之后,将当前目录的redis.conf和子目录src中的redis-server, redis-cli拷贝到bin中。
      (4)修改权限,chmod 777 redis*
     (5)服务端启动命令:./redis-server ./redis.conf
        客户端链接命令:./redis-cli -h localhost -p 6379
        当然也可以使用windows的客户端连接。
三、redis开发篇
   1)客户端采用jedis是个不错的选择。最新版2.7.2兼容redis 2.x 和 3.x。
       jedis下载地址:https://codeload.github.com/xetorthio/jedis/zip/jedis-2.7.2
   2) redis的命令基本上分几大类: 字符串处理类,MAP处理类,SET处理类,LIST处理类等。命令参考文档: http://redisdoc.com/。
      这些命令既可以在客户端中运行,也对应jedis的API方法,对,就这么好用。
      说这么多,给点示例吧.

  
package cn.gov.zjport.learning.redis.redis;

import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @author: zhenggm
 */
public class RedisDemo {
	private static final int DEFAULT_PORT=6379;
	private static final int DEFAULT_TIMEOUT=2000;
	
    JedisPool pool;
    Jedis jedis;
    @Before
    public void setUp() {
        pool = new JedisPool(new JedisPoolConfig(), "localhost", DEFAULT_PORT, DEFAULT_TIMEOUT, "123456");//new JedisPool(new JedisPoolConfig(), "localhost");
        jedis = pool.getResource();
    }

    /**
     * Redis存储初级的字符串
     * CRUD
     */
    @Test
    public void testString(){
        //-----添加数据----------
    	//向key-->name中放入了value-->zhenggm
        jedis.set("name","zhenggm");
        //执行结果:zhenggm
        System.out.println(jedis.get("name"));

        //-----修改数据----------
        //将key-->name的value改为zhangsan
        jedis.set("name","zhangsan");
        //执行结果:zhangsan
        System.out.println(jedis.get("name"));
        
        //-----删除数据----------
        //删除key对应的记录
        jedis.del("name");
        //执行结果:null
        System.out.println(jedis.get("name"));

        /**
         * mset(multi set) 相当于
         * jedis.set("name","zhenggm");
         * jedis.set("company","zjport.gov.cn");
         */
        jedis.mset("name","zhenggm","company","zjport.gov.cn");
        
        /**
         * mget(multi get)
         * 执行结果: [zhenggm, zjport.gov.cn]
         */
        System.out.println(jedis.mget("name","company"));

    }

    /**
     * jedis操作Map
     */
    //@Test
    public void testMap(){
        Map user=new HashMap();
        user.put("name","zhenggm");
        user.put("company","zjport.gov.cn");
        //将map集合保存到缓存中
        jedis.hmset("user",user);
        //获取user的name字段
        System.out.println(jedis.hmget("user", "name"));
        //获取user的全部字段
        System.out.println(jedis.hgetAll("user"));
        
        //删除用户
        jedis.del("user");
    }

    /**
     * jedis操作List
     */
    //@Test
    public void testList(){
       //先向缓存中插入数据
       jedis.lpush("lname","zhangsan");
       jedis.lpush("lname","lisi");
       jedis.lpush("lname","wangwu");
       //再取出所有数据jedis.lrange是按范围取出,
       // 第一个是key,第二个是起始位置,第三个是结束位置,jedis.llen获取长度 -1表示取得所有
       System.out.println(jedis.lrange("lname",0,-1));
       
       //删除list
       jedis.del("lname");
    }

    /**
     * jedis操作Set
     */
    //@Test
    public void testSet(){
        jedis.sadd("sname","zhangsan");
        jedis.sadd("sname","lisi");
        jedis.sadd("sname","wangwu");
       
        System.out.println(jedis.smembers("sname"));//获取所有加入的value
        
        //删除某一个
        jedis.srem("sname", "lisi");
        //删除整个set
        jedis.del("sname");
        
        //批量添加
        jedis.sadd("sname", "zhangsan", "lisi","wangwu"); 
    }
   

    //@Test
    public void test() throws InterruptedException {
    	//返回当前库中所有的key
        System.out.println(jedis.keys("*")); 
        //返回当前db的key数量
        System.out.println(jedis.dbSize());
        //设置"sname" 10秒后过期,过期的数据会被自动删除
        jedis.expire("sname", 10);
        //清空当前数据库数据
        jedis.flushDB();
        //更改DB,1个redis server默认拥有16个DB,所有DB数据物理隔离
        jedis.select(1);
        //清空所有DB
        jedis.flushAll();
        
        jedis.select(0);
        jedis.sadd("sname", "zhangsan","lisi","wangwu");
        //将sname从db0转移至db1
        jedis.move("sname", 1);
        //返回当前db(db0)的key数量
        System.out.println(jedis.dbSize());
        //返回db1的key数量
        jedis.select(1);
        System.out.println(jedis.dbSize());
    } 
}

以上示例的连接池是最简单的,在实际使用中,JedisPoolConfig还有很多属性可以设置。
//控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted。
	private Integer maxTotal;
	//控制一个pool最多有多少个状态为idle(空闲)的jedis实例;
    private Integer maxIdle;
    //控制一个pool最少有多少个状态为idle(空闲)的jedis实例;
    private Integer minIdle;
    //表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
    private Integer maxWaitMillis;
    //在获取连接的时候检查有效性
    private Boolean testOnBorrow;
  


四、redis维护篇
   主要涉及redis.conf的设置
   1)设置redis server的访问密码为123456: requirepass "123456"
   2)建议同时开启rdb和aop的持久化策略,rdb由于每次save都需要全量持久化,因此建议不要频繁持久化,导致性能问题。aop由于每次是增量写日志,因此可以比较频繁的写出,但是文件比较大,且相对容易坏,建议每秒写一次。
    3)默认是不开启aop持久化的,如果要开启,需要将appendonly 改为yes.
   4)maxmemory不要大于系统内存,且要比预估的业务最大容量大一些,因为redis有一部分空间是需要用作同步或者写入磁盘的预留。设置了maxmemory,当业务量超过阀值时,会将设置了过期时间的key,按照最近最少使用的策略删除,如果这些key也删除了,但仍超出,redis可能会崩溃(我用的windows版本出现过)。
   5)有一些重要的命令,如flushall, flushdb, 如果让人不小心执行了,那数据就丢失了,可以在配置文件中使用rename-command flushall "" ,将命令禁用。
   6)主从设置特别简单,主服务器的配置与没有主从配置是一模一样。从服务器的配置也就是使用 slaveof master的地址 master的端口 即可。由于redis的主从同步是另起线程进行的,因此不影响redis-master的服务性能。值得注意的是,由于redis的主从同步是非常快的,因此主服务器如果宕机或其他误操作导致内存丢失,一定要将从服务器的主从同步关闭。否则主服务器一启动,从服务器马上也会同步,导致内存丢失。关闭命令 slaveof no one
   7)如果master设置了密码, 那么还需要设置 masterauth "123456"。
   8)后台运行  daemonize yes
   9)记录日志  logfile "redis.log"
   10)如果主服务器宕机,可以不用停服务修改redis配置。使用客户端工具连上之后,使用config get命令可以看到配置文件中的每个配置项。使用config set命令设置其中的配置项。修改之后,记得使用config rewrite命令,将修改的内容同步到物理配置文件中,这样重启之后,配置也不会丢失。
   11)info命令可以看缓存的实时状态。
   12)monitor命令可以监控缓存的实时运行命令。
   13)如果要关闭server,不要直接kill或者在windows中关闭server窗口,这样会造成还未持久化的数据丢失。可以使用客户端连上之后,敲命令 shutdown.
   14)查看哪些客户端连着, client list
   15) 慢查询统计
       CONFIG SET slowlog-log-slower-than 10000 设置记录操作10000us的慢操作
       CONFIG SET slowlog-max-len 128 最大记录128条慢操作日志
       SLOWLOG LEN 统计当前记录了多少条慢操作日志
       SLOWLOG RESET 重设置慢操作日志
       SLOWLOG GET 100 获取前100条慢操作日志
       Redis 学习笔记_第1张图片
       返回值每个条目由4个字段构成:
       (1)用于表示该条slow log的唯一id
       (2)以unix时间戳表示的日志记录时间
       (3)命令执行时间,单位:微秒
       (4)执行的具体命令
   16) 服务器命令统计
        info commandstats  可以查看服务器命令的执行数,执行总时间,命令平均时间
        CONFIG RESETSTAT 重置统计结果
       
五、常见问题
1、提示 "ERROR: 磁盘空间不足"
   原因:可能客户端连接数超出了redis服务器设置最大连接数,默认最大连接数1w.
  • Redis 学习笔记_第2张图片
  • 大小: 17.8 KB
  • 查看图片附件

你可能感兴趣的:(redis,教程,入门,实战)