一、通过jedis连接redis单机

1.1导入jedis依赖

<dependency>
   	<groupId>redis.clients</groupId>
   	<artifactId>jedis</artifactId>
   	<version>2.9.0</version>
</dependency>

2.2 单实例连接

通过创建单实例jedis对象连接redis服务,代码如下:

// 单实例连接redis
@Test
public void testJedisSingle() {
	Jedis jedis = new Jedis("localhost", 6379);
	jedis.set("name", "bar");
	String name = jedis.get("name");
	System.out.println(name);
	jedis.close();
}

2.3 使用连接池连接

通过单实例连接redis不能对redis连接进行共享,可以使用连接池对redis连接进行共享,提高资源利用率,使用jedisPool连接redis服务,代码如下:

@Test
public void pool() {
	JedisPoolConfig config = new JedisPoolConfig();
	//最大连接数
	config.setMaxTotal(30);
	//最大连接空闲数
	config.setMaxIdle(2);
	//连接redis服务
	JedisPool pool = new JedisPool(config, "localhost", 6379);
	Jedis jedis = null;
	try  {
		jedis = pool.getResource();
		jedis.set("name", "lisi");  //设置值
		String name = jedis.get("name");  //根据key获取值
		System.out.println(name);
	}catch(Exception ex){
		ex.printStackTrace();
	}finally{
		if(jedis != null){
			jedis.close();  //关闭连接
		}
	}
}

二、redis常用五种数据类型

2.1 string类型

redis中没有使用C语言的字符串表示,而是自定义一个数据结构叫SDS(simple dynamic string)即简单动态字符串

打开下载的redis源码包,找到src下的sds.h文件查看sds源码:

struct sdshdr {
    //字符串长度
	unsigned int len;
	//buf数组中未使用的字节数量
    unsigned int free;
	//用于保存字符串
    char buf[];
};

c语言对字符串的存储是使用字符数组,遇到’\0’字符则认为字符串结束,redis的字符串可以存储任何类型的数据,因为任何类型数据都可以表示成二进制,sds结构中的char buf[]就是存储了二进制数据。

redis的字符串是二进制安全什么是二进制安全?简单理解就是存入什么数据取出的还是什么数据。redis中的sds不像c语言处理字符串那样遇到’\0’字符则认证字符串结束,它不会对存储进去的二进制数据进行处理,存入什么数据取出还是什么数据

2.1.1 赋值与取值

通过./redis-cli连接上redis服务进行赋值与取值

SET key value  //赋值
GET key   //取值
127.0.0.1:6379> set test 123
OK
127.0.0.1:6379> get test
"123

注意:当键值(key)不存在时返回空结果

127.0.0.1:6379> get name
(nil)

向尾部追加值
APPEND key value

APPEND的作用是向键值的末尾追加value如果键不存在则将该键的值设置为value,即相当于 SET key value返回值是追加后字符串的总长度

127.0.0.1:6379> set str hello
OK
127.0.0.1:6379> append str " world!"
(integer) 12
127.0.0.1:6379> get str 
"hello world!"

获取字符串长度
STRLEN key

STRLEN命令返回键值的长度,如果键不存在则返回0

127.0.0.1:6379> strlen str 
(integer) 0
127.0.0.1:6379> set str hello
OK
127.0.0.1:6379> strlen str 
(integer) 5

同时设置/获取多个键值
MSET key value [key value …]
MGET key [key …]

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> mget k1 k3
1) "v1"
2) "v3"

2.1.2 应用

public static void Hello() {  
	Jedis jedis = new Jedis("localhost", 6379); 
	try {  
		// 向key-->name中放入了value-->minxr  
		jedis.set("name", "minxr");  
	    String ss = jedis.get("name");  
	    System.out.println(ss);  
	    // 很直观,类似map 将jintao append到已经有的value之后  
	    jedis.append("name", "jintao");  
	    ss = jedis.get("name");  
	    System.out.println(ss);
	    // 2、直接覆盖原来的数据  
	    jedis.set("name", "jintao");  
	    System.out.println(jedis.get("name"));  
	    // 删除key对应的记录  
	    jedis.del("name");  
	    System.out.println(jedis.get("name"));// 执行结果:null  
	    /** 
	     * mset相当于 jedis.set("name","minxr"); jedis.set("jarorwar","aaa"); 
	     */  
	    jedis.mset("name", "minxr", "jarorwar", "aaa");  
	    System.out.println(jedis.mget("name", "jarorwar"));  
	} catch (Exception e) {  
	    e.printStackTrace();  
	} finally {  
	   //RedisUtil.getPool().returnResource(jedis);  
		RedisUtil.closeJedis(jedis);
	}  
	}  
private static void testKey() {  
     Jedis jedis = RedisUtil.getJedis();  
     System.out.println("=============key==========================");  
     // 清空数据  
     System.out.println(jedis.flushDB());  
     System.out.println(jedis.echo("foo"));  
     // 判断key否存在  
     System.out.println(jedis.exists("foo"));  
     jedis.set("key", "values");  
     System.out.println(jedis.exists("key"));  
 }

2.2 hash类型

hash叫散列类型,它提供了字段和字段值的映射字段值只能是字符串类型,不支持散列类型、集合类型等其它类型。如下:
在这里插入图片描述

2.2.1 赋值与取值

HSET key field value	一次只能设置一个字段值
HGET key field			一次只能获取一个字段值
HMSET key field value [field value ...]		一次可以设置多个字段值
HMGET key field [field ...]				一次可以获取多个字段值
HGETALL key
127.0.0.1:6379> hset user username zhangsan 
(integer) 1
127.0.0.1:6379> hget user username
"zhangsan“

HSET命令不区分插入和更新操作,当执行插入操作时HSET命令返回1,当执行更新操作时返回0.

127.0.0.1:6379> hmset user age 20 username lisi 
OK
127.0.0.1:6379> hmget user age username
1) "20"
2) "lisi"
127.0.0.1:6379> hgetall user
1) "age"
2) "20"
3) "username"
4) "lisi"

判断字段是否存在

HEXISTS key field
127.0.0.1:6379> hexists user age		查看user中是否有age字段
(integer) 1
127.0.0.1:6379> hexists user name	查看user中是否有name字段
(integer) 0

HSETNX key field value
当字段不存在时赋值,类似HSET,区别在于如果字段已经存在,该命令不执行任何操作。
127.0.0.1:6379> hsetnx user age 30 如果user中没有age字段则设置age值为30,否则不做任何操作。
删除字段
可以删除一个或多个字段,返回值是被删除的字段个数

HDEL key field [field ...]
127.0.0.1:6379> hdel user age
(integer) 1
127.0.0.1:6379> hdel user age name
(integer) 0
127.0.0.1:6379> hdel user age username
(integer) 1 

只获取字段名或字段值

HKEYS key
HVALS key
127.0.0.1:6379> hmset user age 20 name lisi 
OK
127.0.0.1:6379> hkeys user
1) "age"
2) "name"
127.0.0.1:6379> hvals user
1) "20"
2) "lisi"

获取字段数量

HLEN key
127.0.0.1:6379> hlen user
(integer) 2

2.2.2 应用

public static void testHsh() {  
  System.out.println("==Hash==");  
  Jedis jedis = RedisUtil.getJedis();  
  try {  
      Map<String, String> pairs = new HashMap<String, String>();  
      pairs.put("name", "Akshi");  
      pairs.put("age", "2");  
      pairs.put("sex", "Female");  
      jedis.hmset("kid", pairs);  
      List<String> name = jedis.hmget("kid", "name");// 结果是个泛型的LIST
      System.out.println(name);
      jedis.hdel("kid","age"); //删除map中的某个键值  
      System.out.println(jedis.hmget("kid", "pwd")); // 因为删除了,所以返回的是null  
      System.out.println(jedis.hlen("kid")); // 返回key为user的键中存放的值的个数  
      System.out.println(jedis.exists("kid"));// 是否存在key为user的记录  
      System.out.println(jedis.hkeys("kid"));// 返回map对象中的所有key  
      System.out.println(jedis.hvals("kid"));// 返回map对象中的所有value  

      Iterator<String> iter = jedis.hkeys("kid").iterator();  
      while (iter.hasNext()) {  
          String key = iter.next();  
          System.out.println(key + ":" + jedis.hmget("kid", key));  
      }  

      List<String> values = jedis.lrange("messages", 0, -1);  
      values = jedis.hmget("kid", new String[] { "name", "age", "sex" });  
      System.out.println(values);  
      Set<String> setValues = jedis.zrange("hackers", 0, -1);  
      setValues = jedis.hkeys("kid");  
      System.out.println(setValues);  
      values = jedis.hvals("kid");  
      System.out.println(values);  
      pairs = jedis.hgetAll("kid");  
      System.out.println(pairs);  
    
      // 清空数据  
      System.out.println(jedis.flushDB());  
      // 添加数据  
      jedis.hset("hashs", "entryKey", "entryValue");  
      jedis.hset("hashs", "entryKey1", "entryValue1");  
      jedis.hset("hashs", "entryKey2", "entryValue2");  
      // 判断某个值是否存在  
      System.out.println(jedis.hexists("hashs", "entryKey"));  
      // 获取指定的值  
      System.out.println(jedis.hget("hashs", "entryKey")); // 批量获取指定的值  
      System.out.println(jedis.hmget("hashs", "entryKey", "entryKey1"));  
      // 删除指定的值  
      System.out.println(jedis.hdel("hashs", "entryKey"));  
      // 为key中的域 field 的值加上增量 increment  
      System.out.println(jedis.hincrBy("hashs", "entryKey", 123l));  
      // 获取所有的keys  
      System.out.println(jedis.hkeys("hashs"));  
      // 获取所有的values  
      System.out.println(jedis.hvals("hashs")); 
     } catch (Exception e) {  
         e.printStackTrace();  
     } finally {  
         RedisUtil.getPool().returnResource(jedis);  
     }  
 }  

2.3 list类型

列表类型(list)可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获得列表的某一个片段
列表类型内部是使用双向链表(double linked list)实现的,所以向列表两端添加元素的时间复杂度为0(1),获取越接近两端的元素速度就越快。这意味着即使是一个有几千万个元素的列表,获取头部或尾部的10条记录也是极快的。

2.3.1 赋值与取值

向列表两端增加元素

LPUSH key value [value ...]
RPUSH key value [value ...]
//向列表左边增加元素 
127.0.0.1:6379> lpush list:1 1 2 3
(integer) 3
//向列表右边增加元素 
127.0.0.1:6379> rpush list:1 4 5 6
(integer) 3

从列表两端弹出元素
LPOP key
RPOP key
LPOP命令从列表左边弹出一个元素,会分两步完成,第一步是将列表左边的元素从列表中移除,第二步是返回被移除的元素值。

127.0.0.1:6379> lpop list:1
"3127.0.0.1:6379> rpop list:1
"6

获取列表中元素的个数

LLEN key
127.0.0.1:6379> llen list:1
(integer) 2

获取列表片段

127.0.0.1:6379> lrange list:1 0 2
1) "2"
2) "1"
3) "4"

删除列表中指定的值
LREM key count value
LREM命令会删除列表中前count个值为value的元素,返回实际删除的元素个数。根据count值的不同,该命令的执行方式会有所不同:
 当count>0时, LREM会从列表左边开始删除。
 当count<0时, LREM会从列表后边开始删除。
 当count=0时, LREM删除所有值为value的元素。

2.3.2 应用

public static void testList() {  
  System.out.println("==List==");  
  Jedis jedis = RedisUtil.getJedis();  
  try {  
      // 开始前,先移除所有的内容  
      jedis.del("messages");  
      jedis.rpush("messages", "Hello how are you?");  
      jedis.rpush("messages", "Fine thanks. I'm having fun with redis.");  
      jedis.rpush("messages", "I should look into this NOSQL thing ASAP");  

      // 再取出所有数据jedis.lrange是按范围取出,  
      // 第一个是key,第二个是起始位置,第三个是结束位置,jedis.llen获取长度 -1表示取得所有  
      List<String> values = jedis.lrange("messages", 0, -1);  
      System.out.println(values);  

    // 清空数据  
    System.out.println(jedis.flushDB());  
    // 添加数据  
    jedis.lpush("lists", "vector");  
    jedis.lpush("lists", "ArrayList");  
    jedis.lpush("lists", "LinkedList");  
    // 数组长度  
    System.out.println(jedis.llen("lists"));  
    // 排序  
    //System.out.println(jedis.sort("lists"));  
    // 字串  
    System.out.println(jedis.lrange("lists", 0, 3));  
    // 修改列表中单个值  
    jedis.lset("lists", 0, "hello list!");  
    // 获取列表指定下标的值  
    System.out.println(jedis.lindex("lists", 1));  
    // 删除列表指定下标的值  
    System.out.println(jedis.lrem("lists", 1, "vector"));  
    // 删除区间以外的数据  
    System.out.println(jedis.ltrim("lists", 0, 1));  
    // 列表出栈  
    System.out.println(jedis.lpop("lists"));  
    // 整个列表值  
    System.out.println(jedis.lrange("lists", 0, -1));  
   } catch (Exception e) {  
       e.printStackTrace();  
   } finally {  
       RedisUtil.getPool().returnResource(jedis);  
   }  
}  

2.4 set类型

在集合中的每个元素都是不同的,且没有顺序。

集合类型和列表类型的对比:
在这里插入图片描述
集合类型的常用操作是向集合中加入或删除元素、判断某个元素是否存在等,由于集合类型的Redis内部是使用值为空的散列表实现,所有这些操作的时间复杂度都为0(1)。
Redis还提供了多个集合之间的交集、并集、差集的运算。

2.4.1 赋值与取值

增加/删除元素

SADD key member [member ...]
SREM key member [member ...]
127.0.0.1:6379> sadd set a b c
(integer) 3
127.0.0.1:6379> sadd set a
(integer) 0
127.0.0.1:6379> srem set c d
(integer) 1

获得集合中的所有元素
SMEMBERS key

127.0.0.1:6379> smembers set
1) "b"
2) "a”

判断元素是否在集合中,无论集合中有多少元素都可以极速的返回结果
SISMEMBER key member

127.0.0.1:6379> sismember set a
(integer) 1
127.0.0.1:6379> sismember set h
(integer) 0

2.5 sorted set类型

在集合类型的基础上有序集合类型为集合中的每个元素都关联一个分数,这使得我们不仅可以完成插入、删除和判断元素是否存在在集合中,还能够获得分数最高或最低的前N个元素、获取指定分数范围内的元素等与分数有关的操作。
在某些方面有序集合和列表类型有些相似。
1、二者都是有序的。
2、二者都可以获得某一范围的元素。
但是,二者有着很大区别:
1、列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会变慢。
2、有序集合类型使用散列表实现,所有即使读取位于中间部分的数据也很快。
3、列表中不能简单的调整某个元素的位置,但是有序集合可以(通过更改分数实现)
4、有序集合要比列表类型更耗内存。

2.5.1 赋值与取值

增加元素
向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。返回值是新加入到集合中的元素个数,不包含之前已经存在的元素。
ZADD key score member [score member …]

127.0.0.1:6379> zadd scoreboard 80 zhangsan 89 lisi 94 wangwu 
(integer) 3
127.0.0.1:6379> zadd scoreboard 97 lisi 
(integer) 0

获取元素的分数
ZSCORE key member

127.0.0.1:6379> zscore scoreboard lisi 
"97"

获得排名在某个范围的元素列表
ZRANGE key start stop [WITHSCORES] 照元素分数从小到大的顺序返回索引从start到stop之间的所有元素(包含两端的元素)

127.0.0.1:6379> zrange scoreboard 0 2
1) "zhangsan"
2) "wangwu"
3) "lisi“

ZREVRANGE key start stop [WITHSCORES] 照元素分数从大到小的顺序返回索引从start到stop之间的所有元素(包含两端的元素)

127.0.0.1:6379> zrevrange scoreboard 0 2
1) " lisi "
2) "wangwu"
3) " zhangsan “

如果需要获得元素的分数的可以在命令尾部加上WITHSCORES参数

127.0.0.1:6379> zrange scoreboard 0 1 WITHSCORES
1) "zhangsan"
2) "80"
3) "wangwu"
4) "94"

获得排名在某个范围的元素列表
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

127.0.0.1:6379> ZRANGEBYSCORE scoreboard 90 97 WITHSCORES
1) "wangwu"
2) "94"
3) "lisi"
4) "97"
127.0.0.1:6379> ZRANGEBYSCORE scoreboard 90 (97 WITHSCORES
1) "wangwu"
2) "94127.0.0.1:6379> ZRANGEBYSCORE scoreboard 70 100 limit 1 2
1) "wangwu"
2) "lisi"

增加某个元素的分数,返回值是更改后的分数
ZINCRBY key increment member
给lisi加4分

127.0.0.1:6379> ZINCRBY scoreboard  4 lisi 
"101

获得集合中元素的数量
ZCARD key

127.0.0.1:6379> ZCARD scoreboard
(integer) 3

获得指定分数范围内的元素个数
ZCOUNT key min max

127.0.0.1:6379> ZCOUNT scoreboard 80 90
(integer) 1

按照排名范围删除元素
ZREMRANGEBYRANK key start stop

127.0.0.1:6379> ZREMRANGEBYRANK scoreboard 0 1
(integer) 2 
127.0.0.1:6379> ZRANGE scoreboard 0 -1
1) "lisi"

ZREMRANGEBYSCORE key min max
按照分数范围删除元素

127.0.0.1:6379> zadd scoreboard 84 zhangsan	
(integer) 1
127.0.0.1:6379> ZREMRANGEBYSCORE scoreboard 80 100
(integer) 1

2.5.2 应用

public static void sortedSet() {  
    System.out.println("==SoretedSet==");  
    Jedis jedis = RedisUtil.getJedis();  
    try {  
        jedis.zadd("hackers", 1940, "Alan Kay");  
        jedis.zadd("hackers", 1953, "Richard Stallman");  
        jedis.zadd("hackers", 1965, "Yukihiro Matsumoto");  
        jedis.zadd("hackers", 1916, "Claude Shannon");  
        jedis.zadd("hackers", 1969, "Linus Torvalds");  
        jedis.zadd("hackers", 1912, "Alan Turing");  
        Set<String> setValues = jedis.zrange("hackers", 0, -1);  
        System.out.println(setValues);  
        Set<String> setValues2 = jedis.zrevrange("hackers", 0, -1);  
        System.out.println(setValues2);  
  
     // 清空数据  
     System.out.println(jedis.flushDB());  
     // 添加数据  
     jedis.zadd("zset", 10.1, "hello");  
     jedis.zadd("zset", 10.0, ":");  
     jedis.zadd("zset", 9.0, "zset");  
     jedis.zadd("zset", 11.0, "zset!");  
     // 元素个数  
     System.out.println(jedis.zcard("zset"));  
     // 元素下标  
     System.out.println(jedis.zscore("zset", "zset"));  
     
     // 集合子集  
     System.out.println(jedis.zrange("zset", 0, -1));  
     // 删除元素  
     System.out.println(jedis.zrem("zset", "zset!"));  
     System.out.println(jedis.zcount("zset", 9.5, 10.5));  
     // 整个集合值  
     System.out.println(jedis.zrange("zset", 0, -1)); 
    } catch (Exception e) {  
        e.printStackTrace();  
    } finally {  
        RedisUtil.getPool().returnResource(jedis);  
    }  
}

三、服务器命令

ping
测试连接是否存活

redis 127.0.0.1:6379> ping
PONG
//执行下面命令之前,我们停止redis 服务器
redis 127.0.0.1:6379> ping
Could not connect to Redis at 127.0.0.1:6379: Connection refused
//执行下面命令之前,我们启动redis 服务器
not connected> ping
PONG
//第一个ping 时,说明此连接正常
//第二个ping 之前,我们将redis 服务器停止,那么ping 是失败的
//第三个ping 之前,我们将redis 服务器启动,那么ping 是成功的

echo
在命令行打印一些内容

redis 127.0.0.1:6379> echo HongWan
"HongWan"

select
选择数据库。Redis 数据库编号从0~15,我们可以选择任意一个数据库来进行数据的存取。

redis 127.0.0.1:6379> select 1
OK
redis 127.0.0.1:6379[1]> select 16
(error) ERR invalid DB index
redis 127.0.0.1:6379[16]>
//当选择16 时,报错,说明没有编号为16 的这个数据库

quit
退出连接。

redis 127.0.0.1:6379> quit

dbsize
返回当前数据库中key 的数目。

redis 127.0.0.1:6379> dbsize
(integer) 18
//结果说明此库中有18 个key

info
获取服务器的信息和统计。

redis 127.0.0.1:6379> info
redis_version:2.2.12
redis_git_sha1:00000000
redis_git_dirty:0
arch_bits:32
multiplexing_api:epoll
process_id:28480
uptime_in_seconds:2515
uptime_in_days:0
。。。。
。。。。

flushdb
删除当前选择数据库中的所有key。

redis 127.0.0.1:6379> dbsize
(integer) 18
redis 127.0.0.1:6379> flushdb
OK
redis 127.0.0.1:6379> dbsize
(integer) 0
//在本例中我们将0 号数据库中的key 都清除了。

flushall
删除所有数据库中的所有key。

redis 127.0.0.1:6379[1]> dbsize
(integer) 1
redis 127.0.0.1:6379[1]> select 0
OK
redis 127.0.0.1:6379> flushall
OK
redis 127.0.0.1:6379> select 1
OK
redis 127.0.0.1:6379[1]> dbsize
(integer) 0

在本例中我们先查看了一个1 号数据库中有一个key,然后我切换到0 号库执行flushall 命令,结果1 号库中的key 也被清除了。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐