Redis教程,带你打开nosql数据库的大门

什么是Redis?

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set)有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis 是一个高性能的key-value数据库。
redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部
分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。

Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。

redis的官网地址,非常好记,是redis.io。(特意查了一下,域名后缀io属于国家域名,是british Indian Ocean
territory,即英属印度洋领地) 目前,Vmware在资助着redis项目的开发和维护。

概念介绍完了,接下来,我们将一起学习如何使用Redis。

Redis的数据结构-String

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
其中最常用的为String(字符串)和hash(哈希)两种类型,接下来,我们先介绍第一种,String类型。

首先需要启动Redis,连接之后就可以直接操作Redis了,先做一个简单示例

redis 127.0.0.1:6379> SET name "wumeng"
OK
redis 127.0.0.1:6379> GET name
"wumeng"

上述几行代码,是在内存中新建了一个key为name的字符串,其值为wumeng,设置键使用set命令, 使用get命令可取出相应key的值 ,如上所示get name 值即为wumeng ,需要注意的是,Redis中String类型的值最大只能存储512MB

redis 127.0.0.1:6379> del name 
(interger)1

上述代码表示删除一个key为name的数据,返回1表示删除了一条。

Redis中操作String的命令也有很多,示例如下:

1 SET key value
设置指定 key 的值
2 GET key
获取指定 key 的值。
3 GETRANGE key start end
返回 key 中字符串值的子字符
4 GETSET key value
将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
5 GETBIT key offset
对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
6 MGET key1 [key2…]
获取所有(一个或多个)给定 key 的值。
7 SETBIT key offset value
对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
8 SETEX key seconds value
将值 value 关联到 key ,并将 key 的过期时间设为 seconds (以秒为单位)。
9 SETNX key value
只有在 key 不存在时设置 key 的值。
10 SETRANGE key offset value
用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始。
11 STRLEN key
返回 key 所储存的字符串值的长度。
12 MSET key value [key value …]
同时设置一个或多个 key-value 对。
13 MSETNX key value [key value …]
同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
14 PSETEX key milliseconds value
这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。
15 INCR key
将 key 中储存的数字值增一。
16 INCRBY key increment
将 key 所储存的值加上给定的增量值(increment) 。
17 INCRBYFLOAT key increment
将 key 所储存的值加上给定的浮点增量值(increment) 。
18 DECR key
将 key 中储存的数字值减一。
19 DECRBY key decrement
key 所储存的值减去给定的减量值(decrement) 。
20 APPEND key value
如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。

Redis的数据结构-Hash

Redis中的Hash类似于集合中的Map,它比较适合用于存放一个对象,示例如下

127.0.0.1:6379>  HMSET person name "wumeng"  sex "男"  age "25" 
OK
127.0.0.1:6379>  HGETALL person 
1) "name"
2) "wumeng"
3) "sex "
4) "男"
5) "age "
6) "25"

也可以使用Hset设置单个,例如

127.0.0.1:6379>  HSET person name "wumeng" 
OK
127.0.0.1:6379>  HGET person  name
1) "wumeng"

也可以使用删除命令删除一个指定key的数据,示例如下

127.0.0.1:6379>  HDEL  person name
(integer) 1

Redis中操作Hash的命令也有很多,示例如下:

1 HDEL key field1 [field2]
删除一个或多个哈希表字段
2 HEXISTS key field
查看哈希表 key 中,指定的字段是否存在。
3 HGET key field
获取存储在哈希表中指定字段的值。
4 HGETALL key
获取在哈希表中指定 key 的所有字段和值
5 HINCRBY key field increment
为哈希表 key 中的指定字段的整数值加上增量 increment 。
6 HINCRBYFLOAT key field increment
为哈希表 key 中的指定字段的浮点数值加上增量 increment 。
7 HKEYS key
获取所有哈希表中的字段
8 HLEN key
获取哈希表中字段的数量
9 HMGET key field1 [field2]
获取所有给定字段的值
10 HMSET key field1 value1 [field2 value2 ]
同时将多个 field-value (域-值)对设置到哈希表 key 中。
11 HSET key field value
将哈希表 key 中的字段 field 的值设为 value 。
12 HSETNX key field value
只有在字段 field 不存在时,设置哈希表字段的值。
13 HVALS key
获取哈希表中所有值
14 HSCAN key cursor [MATCH pattern] [COUNT count]
迭代哈希表中的键值对。

Redis的数据结构-List(列表)

Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),示例如下

redis 127.0.0.1:6379> LPUSH database_name redis
(integer) 1
redis 127.0.0.1:6379> LPUSH database_name mongodb
(integer) 2
redis 127.0.0.1:6379> LPUSH database_name neo4j
(integer) 3
redis 127.0.0.1:6379> LPUSH database_name mysql
(integer) 4
redis 127.0.0.1:6379> LRANGE database_name 0 10
1) "mysql"
2) "neo4j"
3) "mongodb"
4) "redis"

使用LPUSH 命令进行插入操作,使用LRANGE命令取出指定key的所有集合

Redis中操作List的命令也有很多,示例如下:

1 BLPOP key1 [key2 ] timeout
移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
2 BRPOP key1 [key2 ] timeout
移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
3 BRPOPLPUSH source destination timeout
从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
4 LINDEX key index
通过索引获取列表中的元素
5 LINSERT key BEFORE|AFTER pivot value
在列表的元素前或者后插入元素
6 LLEN key
获取列表长度
7 LPOP key
移出并获取列表的第一个元素
8 LPUSH key value1 [value2]
将一个或多个值插入到列表头部
9 LPUSHX key value
将一个值插入到已存在的列表头部
10 LRANGE key start stop
获取列表指定范围内的元素
11 LREM key count value
移除列表元素
12 LSET key index value
通过索引设置列表元素的值
13 LTRIM key start stop
对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
14 RPOP key
移除并获取列表最后一个元素
15 RPOPLPUSH source destination
移除列表的最后一个元素,并将该元素添加到另一个列表并返回
16 RPUSH key value1 [value2]
在列表中添加一个或多个值
17 RPUSHX key value
为已存在的列表添加值

Redis的数据结构-Set

Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

redis 127.0.0.1:6379> SADD name wm
(integer) 1
redis 127.0.0.1:6379> SADD name rmx
(integer) 1
redis 127.0.0.1:6379> SADD name hjk
(integer) 1
redis 127.0.0.1:6379> SADD name  ycc
(integer) 0
redis 127.0.0.1:6379> SADD name  wm
(integer) 0
redis 127.0.0.1:6379> SMEMBERS name  
1) "wm"
2) "rmx"
3) "hjk"
4) "ycc"

同样,使用set集合添加数据使用SADD ,获取数据使用SMEMBERS 命令

Redis中操作SET的命令也有很多,示例如下:

1 SADD key member1 [member2]
向集合添加一个或多个成员
2 SCARD key
获取集合的成员数
3 SDIFF key1 [key2]
返回给定所有集合的差集
4 SDIFFSTORE destination key1 [key2]
返回给定所有集合的差集并存储在 destination 中
5 SINTER key1 [key2]
返回给定所有集合的交集
6 SINTERSTORE destination key1 [key2]
返回给定所有集合的交集并存储在 destination 中
7 SISMEMBER key member
判断 member 元素是否是集合 key 的成员
8 SMEMBERS key
返回集合中的所有成员
9 SMOVE source destination member
将 member 元素从 source 集合移动到 destination 集合
10 SPOP key
移除并返回集合中的一个随机元素
11 SRANDMEMBER key [count]
返回集合中一个或多个随机数
12 SREM key member1 [member2]
移除集合中一个或多个成员
13 SUNION key1 [key2]
返回所有给定集合的并集
14 SUNIONSTORE destination key1 [key2]
所有给定集合的并集存储在 destination 集合中
15 SSCAN key cursor [MATCH pattern] [COUNT count]
迭代集合中的元素

Redis 有序集合(sorted set)

Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员,不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序,示例如下

redis 127.0.0.1:6379> ZADD name 1 wm
(integer) 1
redis 127.0.0.1:6379> ZADD name 2 rmx
(integer) 1
redis 127.0.0.1:6379> ZADD name 3 ycc
(integer) 1
redis 127.0.0.1:6379> ZADD name  3 ycc
(integer) 0
redis 127.0.0.1:6379> ZADD name 4 ycc
(integer) 0
redis 127.0.0.1:6379> ZRANGE name 0 10 WITHSCORES

1) "wm"
2) "1"
3) "rmx"
4) "2"
5) "ycc"
6) "4"

sorted set中操作SET的命令也有很多,示例如下:

1 ZADD key score1 member1 [score2 member2]
向有序集合添加一个或多个成员,或者更新已存在成员的分数
2 ZCARD key
获取有序集合的成员数
3 ZCOUNT key min max
计算在有序集合中指定区间分数的成员数
4 ZINCRBY key increment member
有序集合中对指定成员的分数加上增量 increment
5 ZINTERSTORE destination numkeys key [key …]
计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中
6 ZLEXCOUNT key min max
在有序集合中计算指定字典区间内成员数量
7 ZRANGE key start stop [WITHSCORES]
通过索引区间返回有序集合成指定区间内的成员
8 ZRANGEBYLEX key min max [LIMIT offset count]
通过字典区间返回有序集合的成员
9 ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT]
通过分数返回有序集合指定区间内的成员
10 ZRANK key member
返回有序集合中指定成员的索引
11 ZREM key member [member …]
移除有序集合中的一个或多个成员
12 ZREMRANGEBYLEX key min max
移除有序集合中给定的字典区间的所有成员
13 ZREMRANGEBYRANK key start stop
移除有序集合中给定的排名区间的所有成员
14 ZREMRANGEBYSCORE key min max
移除有序集合中给定的分数区间的所有成员
15 ZREVRANGE key start stop [WITHSCORES]
返回有序集中指定区间内的成员,通过索引,分数从高到底
16 ZREVRANGEBYSCORE key max min [WITHSCORES]
返回有序集中指定分数区间内的成员,分数从高到低排序
17 ZREVRANK key member
返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
18 ZSCORE key member
返回有序集中,成员的分数值
19 ZUNIONSTORE destination numkeys key [key …]
计算给定的一个或多个有序集的并集,并存储在新的 key 中
20 ZSCAN key cursor [MATCH pattern] [COUNT count]
迭代有序集合中的元素(包括元素成员和元素分值)

至此,redis中的五种数据结构到此告一段落,我们知道,Redis数据保存在内存中,因此它拥有高效的读写性能,如果redis服务器因不可抗力宕机或者redis服务器需要重启,那么内存中的数据将会消失,为了解决这个问题,我们需要将内存持久化到硬盘中,接下来,我们将介绍持久化到数据至硬盘中的两种方式

Redis的持久化RDB和AOF

Redis持久化方式之一:RDB

RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储

RDB的优势:

1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数 据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。

2). 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。

3). 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。

4). 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。

RDB又存在哪些劣势呢?

1). 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。

2). 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。

Redis持久化方式之二:AOF
AOF持久化以日志的形式记录服务器所处理的每一个写(插入操作)、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。

AOF的优势:
1). 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其 效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变 化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。

2). 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操 作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据 一致性的问题。

3). 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创 建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。

4). AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。

AOF的劣势:

1). 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

2). 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。

二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。

两种方式的配置

RDB持久化配置
Redis会将数据集的快照dump到dump.rdb文件中。此外,我们也可以通过配置文件来修改Redis服务器dump快照的频率,在打开6379.conf文件之后,我们搜索save,可以看到下面的配置信息:

#save 900 1
在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。

#save 300 10
在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。

#save 60 10000
在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。

AOF持久化配置
在Redis的配置文件中存在三种同步方式,它们分别是:

#appendfsync always
每次有数据修改发生时都会写入AOF文件。

#appendfsync everysec
每秒钟同步一次,该策略为AOF的缺省策略。

appendfsync no
从不同步。高效但是数据不会被持久化。(需要改为yes)

使用Jedis API操作Redis

maven依赖

<dependencies>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.9.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
        <version>2.4.2</version>
    </dependency>
</dependencies>

使用连接池的方式连接Redis

@Test
pulic void testRedisPool(){
	//获取连接池对象
	JedisPoolConfig  config = new JedisPoolConfig();
	//设置最大连接数
	config.setMaxTotal(30);
	//设置最大空闲连接数
	config.setMaxIdle(10);
	//获取连接
	JedisPool jsdisPool = new JedisPool(config,"ip","port");
	Jedis jedis = null;
	try{
		jedis = jedisPool.getResource();
		//接下来,就可以使用jedis对象操作Redis
		jedis.set("name","吴猛");
		String name = jedis.get("name");
	}catch(Exception e){
		e.printStackTrace();
	}finally{
		if(jedis!=null){
			jedis..close();
		}
		if(jsdisPool!=null){
			jsdisPool.close();
		}
	}
}

以上代码示例是通过连接池的方式获取Jedis对象,接下来,我们使用Jedis对象操作Redis

与键相关的操作

public static void testKey() {
    System.out.println("====key功能展示====");
    try {
        jedis.select(0);
        System.out.println("清除数据:" + jedis.flushDB());
        System.out.println("判断某个键是否存在:" + jedis.exists("1"));
        System.out.println("新增{1,a}键值对:" + jedis.set("1", "a"));
        System.out.println(jedis.exists("1"));
        System.out.println("新增{2,b}键值对:" + jedis.set("2", "b"));
        System.out.println("系统中所有的键如下:" + jedis.keys("*").toString());
        System.out.println("删除键 1:" + jedis.del("1"));
        System.out.println("判断键 1是否存在:" + jedis.exists("1"));
        System.out.println("设置键 2的过期时间为5s:" + jedis.expire("2", 5));
        TimeUnit.SECONDS.sleep(2);
        System.out.println("查看键 2的剩余生存时间:" + jedis.ttl("2"));
        System.out.println("移除键 2的生存时间:" + jedis.persist("2"));
        System.out.println("查看键 2的剩余生存时间:" + jedis.ttl("2"));
        System.out.println("查看键 2所存储的值的类型:" + jedis.type("2"));
        System.out.println("查看键 2的值:" + jedis.get("2"));

        System.out.println("");
    } catch (Exception e) {
        e.printStackTrace();
    }
}
输出结果:
清除数据:OK
判断某个键是否存在:false
新增{1,a}键值对:OK
true
新增{2,b}键值对 :OK
系统中所有的键如下:[1, 2]
删除键 1:1
判断键 1是否存在:false
设置键 2的过期时间为5s:1
查看键 2的剩余生存时间:3
移除键 2的生存时间:1
查看键 2的剩余生存时间:-1
查看键 2所存储的值的类型:string
查看键 2的值:b

字符串相关操作

public static void testString() {
    try {
        jedis.select(1);
        jedis.flushDB();
        System.out.println("====字符串功能展示====");
        System.out.println("增:");
        System.out.println(jedis.set("a", "1"));
        System.out.println(jedis.set("b", "2"));
        System.out.println(jedis.set("c", "3"));
        System.out.println("删除键 a:" + jedis.del("a"));
        System.out.println("获取键 a:" + jedis.get("a"));
        System.out.println("修改键 b:" + jedis.set("b", "bChanged"));
        System.out.println("获取键 b 的值:" + jedis.get("b"));
        System.out.println("在键 c后面加入值:" + jedis.append("c", "End"));
        System.out.println("获取键 c的值:" + jedis.get("c"));
        System.out.println("增加多个键值对:" + jedis.mset("key01", "value01", "key02", "value02", "key03", "value03"));
        System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03"));
        System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03", "key04"));
        System.out.println("删除多个键值对:" + jedis.del(new String[]{"key01", "key02"}));
        System.out.println("获取多个键值对:" + jedis.mget("key01", "key02", "key03"));

        jedis.flushDB();
        System.out.println("新增键值对防止覆盖原先值:");
        System.out.println(jedis.setnx("key001", "value001"));
        System.out.println(jedis.setnx("key002", "value002"));
        System.out.println(jedis.setnx("key002", "value002-new"));
        System.out.println("获取键key001的值:" + jedis.get("key001"));
        System.out.println("获取键key002的值:" + jedis.get("key002"));

        System.out.println("新增键值对并设置有效时间:");
        System.out.println(jedis.setex("key003", 2, "value003"));
        System.out.println("获取键key003的值:" + jedis.get("key003"));
        TimeUnit.SECONDS.sleep(3);
        System.out.println("获取键key003的值:" + jedis.get("key003"));

        System.out.println("获取原值,更新为新值:");
        System.out.println(jedis.getSet("key002", "key2GetSet"));
        System.out.println("获取键key002的值:" + jedis.get("key002"));

        System.out.println("截取key002的值的字符串:" + jedis.getrange("key002", 2, 5));

        System.out.println("");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出结果

====字符串功能展示====
增:
OK
OK
OK
删除键 a:1
获取键 a:null
修改键 b:OK
获取键 b 的值:bChanged
在键 c后面加入值:4
获取键 c的值:3End
增加多个键值对:OK
获取多个键值对:[value01, value02, value03]
获取多个键值对:[value01, value02, value03, null]
删除多个键值对:2
获取多个键值对:[null, null, value03]
新增键值对防止覆盖原先值:
1
1
0
获取键key001的值:value001
获取键key002的值:value002
新增键值对并设置有效时间:
OK
获取键key003的值:value003
获取键key003的值:null
获取原值,更新为新值:
value002
获取键key002的值:key2GetSet
截取key002的值的字符串:y2Ge

整数和浮点数相关操作

public static void testNumber() {
    try {
        jedis.select(2);
        jedis.flushDB();
        System.out.println("====整数和浮点数功能展示====");
        jedis.set("key001", "1");
        jedis.set("key002", "2");
        jedis.set("key003", "3.3");
        System.out.println("获取键key001的值:" + jedis.get("key001"));
        System.out.println("获取键key002的值:" + jedis.get("key002"));
        System.out.println("将键key001的值+1:" + jedis.incr("key001"));
        System.out.println("获取键key001的值:" + jedis.get("key001"));
        System.out.println("将键key002的值-1:" + jedis.decr("key002"));
        System.out.println("获取键key002的值:" + jedis.get("key002"));
        System.out.println("将key001的值加上整数5:" + jedis.incrBy("key001", 5));
        System.out.println("获取key001的值:" + jedis.get("key001"));
        System.out.println("将key002的值减去整数5:" + jedis.decrBy("key002", 5));
        System.out.println("获取key002的值:" + jedis.get("key002"));

        System.out.println("");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出结果

====整数和浮点数功能展示====
获取键key001的值:1
获取键key002的值:2
将键key001的值+1:2
获取键key001的值:2
将键key002的值-1:1
获取键key002的值:1
将key001的值加上整数5:7
获取key001的值:7
将key002的值减去整数5:-4
获取key002的值:-4

List(列表)相关操作
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

public static void testList() {

    jedis.select(3);
    jedis.flushDB();
    System.out.println("====列表list功能展示====");
    jedis.lpush("collections", "ArrayList", "LinkedList", "Vector", "Stack", "queue");
    jedis.lpush("collections", "HashMap");
    jedis.lpush("collections", "HashMap");
    jedis.lpush("collections", "HashMap");
    jedis.lpush("collections", "HashMap");
    jedis.lpush("number", "1");
    jedis.lpush("number", "2");
    jedis.lpush("number", "3");
    // -1 代表倒数第一个
    System.out.println("collections 的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("collections区间0-2内容:" + jedis.lrange("collections", 0, 2));
    System.out.println("=================");
    // 删除列表指定的值 ,第二个参数为删除的个数(有重复时),后add进去的值先被删,类似于出栈
    System.out.println("删除指定元素个数:" + jedis.lrem("collections", 2, "HashMap"));
    System.out.println("collections 的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("删除区间0-4以外的数据:" + jedis.ltrim("collections", 0, 4));
    System.out.println("collections 的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("collections列表出栈(左端):" + jedis.lpop("collections"));
    System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("collections添加元素,从列表右端,与lpush相对应:" + jedis.rpush("collections", "EnumMap"));
    System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("collections列表出栈(右端):" + jedis.rpop("collections"));
    System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("修改collections指定下标1的内容:" + jedis.lset("collections", 1, "LinkedArrayList"));
    System.out.println("collections的内容:" + jedis.lrange("collections", 0, -1));
    System.out.println("=================");
    System.out.println("collections的长度:" + jedis.llen("collections"));
    System.out.println("获取collections下标为2的元素:" + jedis.lindex("collections", 2));
    System.out.println("=================");
    jedis.lpush("sortedList", "3", "6", "2", "0", "7", "4");
    System.out.println("sortedList排序前:" + jedis.lrange("sortedList", 0, -1));
    System.out.println(jedis.sort("sortedList"));
    System.out.println("sortedList排序后:" + jedis.lrange("sortedList", 0, -1));
    
    System.out.println("");  
}

输出结果

====列表list功能展示====
collections 的内容:[HashMap, HashMap, HashMap, HashMap, queue, Stack, Vector, LinkedList, ArrayList]
collections区间0-2内容:[HashMap, HashMap, HashMap]
================= 
删除指定元素个数:2
collections 的内容:[HashMap, HashMap, queue, Stack, Vector, LinkedList, ArrayList]
删除区间0-4以外的数据:OK
collections 的内容:[HashMap, HashMap, queue, Stack, Vector]
collections列表出栈(左端):HashMap
collections的内容:[HashMap, queue, Stack, Vector]
collections添加元素,从列表右端,与lpush相对应:5
collections的内容:[HashMap, queue, Stack, Vector, EnumMap]
collections列表出栈(右端):EnumMap
collections的内容:[HashMap, queue, Stack, Vector]
修改collections指定下标1的内容:OK
collections的内容:[HashMap, LinkedArrayList, Stack, Vector]
================= 
collections的长度:4
获取collections下标为2的元素:Stack
================ 
sortedList排序前:[4, 7, 0, 2, 6, 3]
[0, 2, 3, 4, 6, 7]
sortedList排序后:[4, 7, 0, 2, 6, 3]

集合(Set)相关操作
Redis的Set是string类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

public static void testSet() {
    try {
        jedis.select(4);
        jedis.flushDB();
        System.out.println("========测试集合(set)=========");
        System.out.println("集合set添加数据:" + jedis.sadd("setElement", "e1", "e7", "e3", "e6", "e0", "e4"));
        System.out.println(jedis.sadd("setElement", "e6"));
        System.out.println("setElement的所有元素:" + jedis.smembers("setElement"));
        System.out.println("删除元素e0:" + jedis.srem("setElement", "e0"));
        System.out.println("setElement的所有元素:" + jedis.smembers("setElement"));
        System.out.println("删除两个元素e7和e6:" + jedis.srem("setElement", "e7", "e6"));
        System.out.println("setElement的所有元素为:" + jedis.smembers("setElement"));
        System.out.println("随机的移除集合中的一个元素:" + jedis.spop("setElement"));
        System.out.println("随机的移除集合中的一个元素:" + jedis.spop("setElement"));
        System.out.println("setElement的所有元素为:" + jedis.smembers("setElement"));
        System.out.println("setElement中包含元素的个数:" + jedis.scard("setElement"));
        System.out.println("e3是否在setElement中:" + jedis.sismember("setElement", "e3"));
        System.out.println("e1是否在setElement中:" + jedis.sismember("setElement", "e1"));

        System.out.println("=================");
        System.out.println(jedis.sadd("setElement1", "e1", "e2", "e4", "e3", "e0", "e8", "e7", "e5"));
        System.out.println(jedis.sadd("setElement2", "e1", "e2", "e4", "e3", "e0", "e8"));
        System.out.println("将setElement1中删除e1并存入setElement3中:" + jedis.smove("setElement1", "setElement3", "e1"));
        System.out.println("将setElement1中删除e2并存入setElement3中:" + jedis.smove("setElement1", "setElement3", "e2"));
        System.out.println("setElement1中的元素:" + jedis.smembers("setElement1"));
        System.out.println("setElement3中的元素:" + jedis.smembers("setElement3"));

        System.out.println("集合运算:");
        System.out.println("setElement1中的元素:" + jedis.smembers("setElement1"));
        System.out.println("setElement2中的元素:" + jedis.smembers("setElement2"));
        System.out.println("setElement1和setElement2的交集:" + jedis.sinter("setElement1", "setElement2"));
        System.out.println("setElement1和setElement2的并集:" + jedis.sunion("setElement1", "setElement2"));
        // setElement1中有,setElement2中没有
        System.out.println("setElement1和setElement2的差集:" + jedis.sdiff("setElement1", "setElement2"));

        System.out.println("");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出结果:

========测试集合(set)=========
集合set添加数据:6
0
setElement的所有元素:[e3, e6, e1, e7, e0, e4]
删除元素e0:1
setElement的所有元素:[e6, e3, e1, e7, e4]
删除两个元素e7和e6:2
setElement的所有元素为:[e3, e1, e4]
随机的移除集合中的一个元素:e3
随机的移除集合中的一个元素:e4
setElement的所有元素为:[e1]
setElement中包含元素的个数:1
e3是否在setElement中:false
e1是否在setElement中:true
================= 
8
6
将setElement1中删除e1并存入setElement3中:1
将setElement1中删除e2并存入setElement3中:1
setElement1中的元素:[e5, e8, e3, e7, e0, e4]
setElement3中的元素:[e1, e2]
集合运算:
setElement1中的元素:[e5, e8, e3, e7, e0, e4]
setElement2中的元素:[e3, e4, e2, e8, e1, e0]
setElement1和setElement2的交集:[e3, e4, e8, e0]
setElement1和setElement2的并集:[e5, e8, e3, e1, e7, e0, e2, e4]
setElement1和setElement2的差集:[e5, e7]

hash相关操作
Redis hash 是一个键值(key=>value)对集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

public static void testHash() {

    try {
        System.out.println("=======集合(Set)=======");
        jedis.select(5);
        jedis.flushDB();
        Map<String, String> map = new HashMap<String, String>();
        map.put("key001", "value001");
        map.put("key002", "value002");
        map.put("key003", "value003");
        jedis.hmset("hash", map);
        jedis.hset("hash", "key004", "value004");
        // return Map<String,String>
        System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));
        // return Set<String>
        System.out.println("散列hash的所有键为:" + jedis.hkeys("hash"));
        // return List<String>
        System.out.println("散列hash的所有值为:" + jedis.hvals("hash"));
        System.out.println("将key006保存的值加上一个整数,如果key006不存在则添加key006:" + jedis.hincrBy("hash", "key006", 6));
        System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));
        System.out.println("将key006保存的值加上一个整数,如果key006不存在则添加key006:" + jedis.hincrBy("hash", "key006", 3));
        System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));
        System.out.println("删除一个或者多个键值对:" + jedis.hdel("hash", "key002"));
        System.out.println("散列hash的所有键值对为:" + jedis.hgetAll("hash"));
        System.out.println("散列hash中键值对的个数:" + jedis.hlen("hash"));
        System.out.println("判断hash中是否存在key002:" + jedis.hexists("hash", "key002"));
        System.out.println("判断hash中是否存在key003:" + jedis.hexists("hash", "key003"));
        System.out.println("获取hash中的值:" + jedis.hmget("hash", "key003"));
        System.out.println("获取hash中的值:" + jedis.hmget("hash", "key003", "key004"));

        System.out.println("");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出结果:

=======集合(Set)=======
散列hash的所有键值对为:{key004=value004, key003=value003, key002=value002, key001=value001}
散列hash的所有键为:[key004, key003, key002, key001]
散列hash的所有值为:[value001, value003, value002, value004]
将key006保存的值加上一个整数,如果key006不存在则添加key006:6
散列hash的所有键值对为:{key004=value004, key003=value003, key006=6, key002=value002, key001=value001}
将key006保存的值加上一个整数,如果key006不存在则添加key006:9
散列hash的所有键值对为:{key004=value004, key003=value003, key006=9, key002=value002, key001=value001}
删除一个或者多个键值对:1
散列hash的所有键值对为:{key004=value004, key003=value003, key006=9, key001=value001}
散列hash中键值对的个数:4
判断hash中是否存在key002:false
判断hash中是否存在key003:true
获取hash中的值:[value003]
获取hash中的值:[value003, value004]

有序集合相关操作
zset(sorted set:有序集合)
Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。

public static void testSortSet() {

    try {
        System.out.println("=======有序集合=======");
        jedis.select(6);
        jedis.flushDB();
        Map<String, Double> map = new HashMap<String, Double>();
        map.put("key2", 1.2);
        map.put("key3", 4.0);
        map.put("key4", 5.0);
        map.put("key5", 0.2);
        System.out.println(jedis.zadd("zset", 3, "key1"));
        System.out.println(jedis.zadd("zset", map));
        System.out.println("zset中的所有元素:" + jedis.zrange("zset", 0, -1));
        System.out.println("zset中的所有元素:" + jedis.zrangeWithScores("zset", 0, -1));
        System.out.println("zset中的所有元素:" + jedis.zrangeByScore("zset", 0, 100));
        System.out.println("zset中的所有元素:" + jedis.zrangeByScoreWithScores("zset", 0, 100));
        System.out.println("zset中key2的分值:" + jedis.zscore("zset", "key2"));
        System.out.println("zset中key2的排名:" + jedis.zrank("zset", "key2"));
        System.out.println("删除zset中的元素key3:" + jedis.zrem("zset", "key3"));
        System.out.println("zset中的所有元素:" + jedis.zrange("zset", 0, -1));
        System.out.println("zset中元素的个数:" + jedis.zcard("zset"));
        System.out.println("zset中分值在1-4之间的元素的个数:" + jedis.zcount("zset", 1, 4));
        System.out.println("key2的分值加上5:" + jedis.zincrby("zset", 5, "key2"));
        System.out.println("key3的分值加上4:" + jedis.zincrby("zset", 4, "key3"));
        System.out.println("zset中的所有元素:" + jedis.zrange("zset", 0, -1));

        System.out.println("");

    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出结果:

=======有序集合=======
1
4
zset中的所有元素:[key5, key2, key1, key3, key4]
zset中的所有元素:[[[107, 101, 121, 53],0.2], [[107, 101, 121, 50],1.2], [[107, 101, 121, 49],3.0], [[107, 101, 121, 51],4.0], [[107, 101, 121, 52],5.0]]
zset中的所有元素:[key5, key2, key1, key3, key4]
zset中的所有元素:[[[107, 101, 121, 53],0.2], [[107, 101, 121, 50],1.2], [[107, 101, 121, 49],3.0], [[107, 101, 121, 51],4.0], [[107, 101, 121, 52],5.0]]
zset中key2的分值:1.2
zset中key2的排名:1
删除zset中的元素key3:1
zset中的所有元素:[key5, key2, key1, key4]
zset中元素的个数:4
zset中分值在1-4之间的元素的个数:2
key2的分值加上5:6.2
key3的分值加上4:4.0
zset中的所有元素:[key5, key1, key3, key4, key2]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值