Redis介绍

概念:

redis可以在服务器启动一个服务,将数据缓存到服务器内存,读写缓存采用key-value的方式,类似于操作一个内存中的Map。

服务器与客户端采用TCP协议,用socket连接发送命令的方式通信,每一条命令都异"\r\n"结尾。

安装:

linux下:

1、下载安装包

wget http://download.redis.io/releases/redis-2.8.13.tar.gz

 

2、解压,进入主目录,编译

tar xzf redis-2.8.13.tar.gz

cd redis-2.8.13

make

 

3、启动服务

src/redis-server

Redis 服务端的默认连接端口是 6379

注意需要设置防火墙开启6379端口或者关闭防火墙service iptables stop,否则客户端无法访问。

4、客户端验证

新开一个会话窗口,进入redis主目录,然后执行

src/redis-cli

操作数据:

5、将Redis作为 Linux 服务随机启动

  vi /etc/rc.local, 使用vi编辑器打开随机启动配置文件,并在其中加入下面一行代码。

  /root/4setup/redis-2.8.13/src/redis-server

 

Jedis客户端操作

配置

多种客户端可以操作redis服务,最常用的是jedis,配置:

maven中加入依赖:

        <dependency>

            <groupId>redis.clients</groupId>

            <artifactId>jedis</artifactId>

            <version>2.4.2</version>

            <type>jar</type>

            <scope>compile</scope>

        </dependency>

客户端操作方式

普通方式

        // 创建jedis对象,传入服务器的ip和端口

        Jedis jedis = new Jedis("192.168.121.130", 6379);

        // 设置值

        String result = jedis.set("kkk", "hello");

        // 输出"kkk=hello"

        System.out.println("kkk=" + jedis.get("kkk"));

        // 输出"OK"

        System.out.println("result=" + result);

        // 释放连接

     jedis.disconnect();

 

事务方式

目的是当有其他的线程也在同时操作这个redis服务时,这里的多个操作之间不会有其他线程插队的操作。

        // 创建jedis对象,传入服务器的ip和端口

        Jedis jedis = new Jedis("192.168.121.130", 6379);

        // 开启事务

     Transaction tx = jedis.multi();

     // set

     tx.set("name", "张三");

     tx.set("age", "55");

     // 取得返回结果

     List<Object> results = tx.exec();

    for (Object object : results) {

         System.out.println("result=" + object); // 输出"OK"

        }

     // 释放连接

     jedis.disconnect();

管道方式(异步方式)

采用异步方式,一次发送多个指令,不同步等待其返回结果而代码继续往下执行。

        // 创建jedis对象,传入服务器的ip和端口

        Jedis jedis = new Jedis("192.168.121.130", 6379);

        // 开启管道

     Pipeline pipeline = jedis.pipelined();

     // set

     pipeline.set("name", "张三");

     pipeline.set("age", "55");

     // 取得返回结果

     List<Object> results = pipeline.syncAndReturnAll();

    for (Object object : results) {

         System.out.println("result=" + object); // 输出"OK"

        }

     // 释放连接

     jedis.disconnect();

 

管道中使用事务

        // 创建jedis对象,传入服务器的ip和端口

        Jedis jedis = new Jedis("192.168.121.130", 6379);

        // 开启管道

     Pipeline pipeline = jedis.pipelined();

     // 开启事务

     pipeline.multi();

     // set

     pipeline.set("name", "张三");

     pipeline.set("age", "55");

     // 执行事务

     pipeline.exec();

     // 取得返回结果

     List<Object> results = pipeline.syncAndReturnAll();

    for (Object object : results) {

         System.out.println("result=" + object);

         // 依次输出

//         result=OK

//         result=QUEUED

//         result=QUEUED

//         result=[OK, OK]

        }

     // 释放连接

     jedis.disconnect();

分布式直连同步调用

同时操作多个redis服务,

 

        // 创建shards,传入操作redis服务的ip和端口

        List<JedisShardInfo> shards = Arrays.asList(

     new JedisShardInfo("192.168.121.130",6379),

     new JedisShardInfo("192.168.121.130",6380));

 

     ShardedJedis sharding = new ShardedJedis(shards);

 

     // set数据

     String result1 = sharding.set("name", "张三");

     String result2 = sharding.set("age", "55");

     System.out.println(result1); // 输出OK

     System.out.println(result2); // 输出OK

     // 释放连接

     sharding.disconnect();

分布式直连异步调用(管道)

多了一个管道操作

        // 创建shards,传入操作redis服务的ip和端口

        List<JedisShardInfo> shards = Arrays.asList(

     new JedisShardInfo("192.168.121.130",6379),

     new JedisShardInfo("192.168.121.130",6380));

 

     ShardedJedis sharding = new ShardedJedis(shards);

     // 创建管道

     ShardedJedisPipeline shardedJedisPipeline = sharding.pipelined();

     // set数据

     shardedJedisPipeline.set("name", "张三");

     shardedJedisPipeline.set("age", "55");

     // 管道同步数据

     List<Object> results = shardedJedisPipeline.syncAndReturnAll();

     for (Object object : results) {

            System.out.println(object); // 输出OK

        }

     // 释放连接

     sharding.disconnect();

分布式连接池同步调用

采用连接池的方式调用,避免线程冲突等问题

//        // 创建shards,传入操作redis服务的ip和端口

        List<JedisShardInfo> shards = Arrays.asList(

new JedisShardInfo("192.168.121.130",6379),

new JedisShardInfo("192.168.121.130",6379));

 

        //创建连接池

     ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);

 

     // 取得连接池的resource连接资源

     ShardedJedis one = pool.getResource();

 

     // set数据

     String result1 = one.set("name", "张三");

     String result2 = one.set("age", "55");

     System.out.println(result1); // 输出OK

     System.out.println(result2); // 输出OK

     // 交还resource连接资源

     pool.returnResource(one);

 

     // 释放连接,注意不是用的discontect

     pool.destroy();

 

分布式连接池异步调用(管道)

用pool的resource创建管道操作redis服务

//        // 创建shards,传入操作redis服务的ip和端口

        List<JedisShardInfo> shards = Arrays.asList(

new JedisShardInfo("192.168.121.130",6379),

new JedisShardInfo("192.168.121.130",6380));

 

        //创建连接池

     ShardedJedisPool pool = new ShardedJedisPool(new JedisPoolConfig(), shards);

 

     // 取得连接池的resource连接资源

     ShardedJedis one = pool.getResource();

 

     // 创建管道

     ShardedJedisPipeline shardedJedisPipeline = one.pipelined();

      

     // set数据

     shardedJedisPipeline.set("name", "张三");

     shardedJedisPipeline.set("age", "55");

     // 管道同步数据

     List<Object> results = shardedJedisPipeline.syncAndReturnAll();

     for (Object object : results) {

            System.out.println(object); // 输出OK

        }

     // 交还resource连接资源

     pool.returnResource(one);

 

     // 释放连接,注意不是用的discontect

     pool.destroy();

    }

 

注意:

1、事务和管道都是异步操作,会新开线程,因此在事务和管道中不能同步查询。

2、分布式中,连接池的性能高于直连。

3、由于事务和管道都是异步,因此在管道中没有必要再进行事务。

4、分布式调用中不支持事务,因为事务是在服务器端实现,而在分布式中,每批次的调用对象都可能访问不同的机器,所以,没法进行事务。

 

操作方式:

通用操作

flushDB清空记录

清空redis服务器的所有记录

        jedis.flushDB();// 返回"OK"

 

String操作

set设置值

        jedis.set("name", "张三"); // name"张三"

append追加值

字符串后面追加:

        jedis.set("name", "张三"); // name"张三"

        jedis.append("name", "123"); // name "张三123"

del删除值

        jedis.del("name"); //name null

也可以同时删除多个,如:

        jedis.del("name", "age");

        jedis.del(new String[] {"name", "age"});

mset、mget批量存取

一次性存取多个值。

        jedis.mset("name", "张三", "age", "kkk", "address", "山东");

        List<String> results = jedis.mget("name", "age", "address");

        for (String result : results) {

            System.out.println(result); // 依次输出"张三","kkk","山东"

        }

exists判断是否存在

查询key是否存在,返回true或false(boolean类型)

        jedis.exists("name");

 

setnx不存在时设置

        jedis.set("name", "张三");

        jedis.setnx("name", "王五"); // name还是"张三",因为key已经存在

        jedis.setnx("age", "33"); // age变成了"33"

setex设置时指定有效期

设置值的时候指定有效期,过期后自动移除,单位是"秒"

        jedis.setex("name", 3, "张三");

这个值的有效期为3秒。

 

getSet设置新值,返回旧值

        jedis.set("name", "张三");

        jedis.getSet("name", "李四"); // 方法返回值是"张三",同时将name设置为了"李四"

 

getrange截取字符串返回

        jedis.set("name", "123456789");

        System.out.println(jedis.getrange("name", 2, 3)); // 输出'34'

2、3分别代表开始和结束为止,从0开始算。

 

list操作

lpush、rpush存数据

        jedis.lpush("userList", "a"); // userList=a

        jedis.rpush("userList", "b"); // userList=ab

        jedis.lpush("userList", "c"); // userList=cab

lpush前面加list元素、rpush后面加list元素

也可以一次性写多个参数,如:

        jedis.rpush("userList", "a", "b", "c"); // userList=abc

lrange取子串

传入起始位置、结束位置截取list,从0开始算

 

        jedis.flushDB();

        jedis.rpush("userList", "a", "b", "c"); // userList=abc

        System.out.println(jedis.lrange("userList", 0, 0)); // [a]

        System.out.println(jedis.lrange("userList", 0, 2)); // [a,b,c]

        System.out.println(jedis.lrange("userList", 1, 2)); // [b,c]

        System.out.println(jedis.lrange("userList", 1, -1)); // [a,b,c],-1表示末尾

        System.out.println(jedis.lrange("userList", -1, -1)); // [c],-1表示末尾

一般使用lrange("userList ", 0, -1)取所有元素

llen取list长度

        jedis.flushDB();

        jedis.rpush("userList", "a", "b", "c"); // userList=abc

        System.out.println(jedis.llen("userList")); // 3

llen如果取其他类型,如string的长度,会报异常,如果取的key不存在,返回0.

sort排序

        jedis.flushDB();

        jedis.rpush("userList", "5", "1.5", "3"); // userList=5,1.5,3

        System.out.println(jedis.sort("userList")); // [1.5,3,5]

排序时所有元素都必须为数字,如果不合法数字,会报JedisDataException异常。

lset设置单个list元素值

        第二个参数是位置,最后一个参数是新值。

        jedis.flushDB();

        jedis.rpush("userList", "a", "b", "c"); // userList=a,b,c

        jedis.lset("userList", 0, "aa"); // userList=aa,b,c

        jedis.lset("userList", -1, "cc"); // userList=aa,b,cc,-1代表最后一个

        System.out.println(jedis.lrange("userList", 0, -1)); // userList=aa,b,cc

 

lindex获取指定下标的值(相当于java的list.get(n))

        jedis.rpush("userList", "a", "b", "c"); // userList=a,b,c

        System.out.println(jedis.lindex("userList", 1)); // b

 

lrem根据value删除元素

第二个参数是删除的个数。

        jedis.flushDB();

        jedis.rpush("userList", "a", "b", "b", "b", "c"); // userList=a,b,b,b,c

        jedis.lrem("userList", 2, "b"); // userList=a,b,c

删除两个"b"还剩一个,所以最后是a,b,c,如果要全部删除,则传入0

ltrim删除指定范围以外的元素

        jedis.rpush("userList", "a", "b", "c", "d", "e"); // userList=a,b,c,d,e

        jedis.ltrim("userList", 2, 3); // userList=c,d,2到第3个元素是c,d,除此以为全部删除

lpop左侧出栈,rpop右侧出栈

        jedis.flushDB();

        jedis.rpush("userList", "a", "b", "c"); // userList=a,b,c

        System.out.println(jedis.lpop("userList")); // 左侧出栈,输出a,此时userList=b,c,先进先出

set操作

set中的元素是没有顺序的,同时也没有相同的元素,存相同的元素操作相当于没有执行。

sadd存数据

        jedis.flushDB();

        jedis.sadd("userSet", "a");

        jedis.sadd("userSet", "b");

        jedis.sadd("userSet", "c"); // userSet=[b, c, a]

简写:

        jedis.sadd("userSet", "a", "b", "c");

 

smembers取数据

        jedis.sadd("userSet", "a", "b", "c"); // userSet=[b, c, a]

        Set<String> userSet = jedis.smembers("userSet");

sismember判断value是否在列表中

        jedis.sadd("userSet", "a", "b"); // userSet=[b, a]

        // 判断value是否在列表中

        jedis.sismember("userSet", "b"); // true

srem删除指定元素

        jedis.sadd("userSet", "a", "b"); // userSet=[a, b]

        jedis.srem("userSet", "b"); // userSet=[a]

spop出栈

        jedis.sadd("userSet", "a", "b", "c");

        System.out.println(jedis.smembers("userSet")); // 输出[b, c, a]

        System.out.println(jedis.spop("userSet")); // 输出b

        System.out.println(jedis.smembers("userSet")); // 输出[c, a]

由于没有顺序,所以随机pop出了一个元素

sinter取交集

参数可以是1个或多个

        jedis.sadd("userSet1", "a", "b");

        jedis.sadd("userSet2", "b", "c", "d");

        System.out.println(jedis.sinter("userSet1", "userSet2")); // 输出[b]

sunion取交集

参数可以是1个或多个

        jedis.sadd("userSet1", "a", "b");

        jedis.sadd("userSet2", "b", "c", "d");

        jedis.sadd("userSet3", "e");

    System.out.println(jedis.sunion("userSet1","userSet2","userSet3"); // 输出[d, e, b, c, a]

sdiff取差集

获取在第一个集合中存在,而在后面几个集合中不存在的元素。

        jedis.sadd("userSet1", "a", "b", "c");

        jedis.sadd("userSet2", "a", "k");

        jedis.sadd("userSet3", "b", "j");

    System.out.println(jedis.sdiff("userSet1","userSet2","userSet3")); // 输出[c]

SortedSet操作

可排序的Set

zadd存数据

        jedis.zadd("userSet", 52.78, "c");

        jedis.zadd("userSet", 23.2, "b");

 

第二个参数是下标(叫做score),下标是double类型的。最后一个参数是值(叫做member)。由于是可排序Set,因此每次新加入元素都会按下标score重新排序。顺序在取子集合等情况下会用到。

zcard取元素个数

        jedis.zadd("userSet", 52.78, "c");

        jedis.zadd("userSet", 23.2, "b");

        // 元素个数

        System.out.println(jedis.zcard("userSet")); // 输出2

zcore通过值取下标

        jedis.zadd("userSet", 52.78, "c");

        jedis.zadd("userSet", 23.2, "b");

 

        System.out.println(jedis.zscore("userSet", "b")); // 输出23.2

zrange取子集合

        jedis.zadd("userSet", 52.78, "c");

        jedis.zadd("userSet", 23.2, "b");

        jedis.zadd("userSet", 9.2, "a");

        jedis.zadd("userSet", 120, "d");

        // 集合子集

        jedis.zrange("userSet", 1, -1); // [a, b, c]

        jedis.zrange("userSet", 0, -1); // [a, b, c, d]

一般用jedis.zrange("userSet", 0, -1)取整个集合,-1代表最后。

zrem删除元素

        jedis.zadd("userSet", 52.78, "c");

        jedis.zadd("userSet", 23.2, "b");

        jedis.zadd("userSet", 9.2, "a");

        jedis.zadd("userSet", 120, "d");

 

        // 删除元素

        System.out.println(jedis.zrem("userSet", "d", "c")); // 输出2,表示删除了2个元素,此时userSet=[a, b]

 

zcount统计某一score区间的元素个数

统计时包含前后边界。

        jedis.zadd("userSet", 52.78, "c");

        jedis.zadd("userSet", 23.2, "b");

        jedis.zadd("userSet", 9.2, "a");

        jedis.zadd("userSet", 120, "d");

 

        jedis.zcount("userSet", 23.2, 52.78); // 输出2bc在这个范围内

        System.out.println(jedis.zcount("userSet", 23.3, 52.78)); // 输出1,只有c在这个范围

Hash操作(Map操作)

整个redis可以看做一个Map<String, Object>,而Hash相当于这个Map中的Map<String, String>,通过key先取出Map,再通过取出Map中的key取得value。

结构类似于Map<String, Map<String, Object>>

hset存数据

        jedis.hset("userMap", "name", "zhangsan");

        jedis.hset("userMap", "age", "33");

        jedis.hset("userMap", "address", "sichuan");

为userMap添加了三个键值对。

hexists判断某个key是否存在

        jedis.hset("userMap", "name", "zhangsan");

        jedis.hset("userMap", "age", "33");

        // 判断某个值是否存在

        jedis.hexists("userMap", "name"); // 返回true

hget通过key获取value

        jedis.hget("userMap", "name"); // 返回zhangsan

hmget批量通过key获取返回的List<String>

        // 批量获取指定的值

        List<String> results = jedis.hmget("userMap", "name", "address");// 返回[zhangsan, sichuan]

可以有多个

hdel通过key删除指定值

        // 删除指定的值

        System.out.println(jedis.hdel("userMap", "address", "age")); // 返回2,此时userMap变成[zhangsan]

hincrBy为int类型数据累加

        jedis.hset("userMap", "age", "33");

        // key中的域 field 的值加上增量 increment

        System.out.println(jedis.hincrBy("userMap", "age", 5L)); // 输出38,同时更新userMap

        System.out.println(jedis.hincrBy("userMap", "age", 3)); // 输出41,同时更新userMap

注意这里的参数类型是Long,更新map的同时返回累加后的数据

hkeys、hvals获取所有的key和value

        jedis.hset("userMap", "name", "zhangsan");

        jedis.hset("userMap", "age", "33");

        jedis.hset("userMap", "age", "chengdu");

        // 获取所有的keys

        Set<String> keys = jedis.hkeys("userMap"); // 返回[age, name]

        // 获取所有的values

        List<String> values = jedis.hvals("userMap"); // 返回[zhangsan, chengdu]

注意获取的keys是Set<String>,values是List<String>

posted @ 2020-12-16 10:44  吴克兢  阅读(80)  评论(0)    收藏  举报