1. 介绍
Redis是一个开源,高级的键值存储解决方案,用于构建高性能,可扩展的Web应用程序。
Redis有三个主要特点,使它优越于其它键值数据存储系统
- Redis将其数据库完全保存在内存中,仅使用磁盘进行持久化。
- 与其它键值数据存储相比,Redis有一组相对丰富的数据类型。
- Redis可以将数据复制到任意数量的从机中。
1.1 Redis的优点
- 异常快
Redis非常快,每秒可执行大约110000次的设置(SET)操作,每秒大约可执行81000次的读取/获取(GET)操作。 - 支持丰富的数据类型
Redis支持开发人员常用的大多数数据类型,例如列表,集合,排序集和散列等等。 - 操作具有原子性
所有Redis操作都是原子操作,这确保如果两个客户端并发访问,Redis服务器能接收更新的值。 - 多实用工具
Redis是一个多实用工具,可用于多种用例,如:缓存,消息队列(Redis本地支持发布/订阅),应用程序中的任何短期数据,例如,web应用程序中的会话,网页命中计数等。
1.2 Redis数据类型
Redis支持5种数据类型。
Redis命令不区分大小写,如SET,Set和set都是同一个命令。
字符串Strings
Redis中的字符串是一个字节序列。Redis中的字符串是二进制安全的,这意味着它们的长度不由任何特殊的终止字符决定。因此,可以在一个字符串中存储高达512兆字节的任何内容。
127.0.0.1:6379> set name "xiezhenwie"
OK
127.0.0.1:6379> get name
"xiezhenwie"
散列/哈希(类似于map)Hashes
Redis散列/哈希(Hashes)是键值对的集合。Redis散列/哈希是字符串字段和字符串值之间的映射。因此,它们用于表示对象。
每个散列/哈希可以存储多达2^32 - 1个健-值对(超过40亿个)。
列表Lists
Redis列表只是字符串列表,按插入顺序排序。您可以向Redis列表的头部或尾部添加元素。
列表的最大长度为2^32 - 1个元素(4294967295,每个列表可容纳超过40亿个元素)。
集合Sets
Redis集合是字符串的无序集合,重复的元素只会被添加一次。
一个集合中的最大成员数量为2^32 - 1(即4294967295,每个集合中元素数量可达40亿个)个。
可排序集合Sorted Sets
Redis可排序集合类似于Redis集合,是不重复的字符串集合。 不同之处在于,排序集合的每个成员都与分数相关联,这个分数用于按最小分数到最大分数来排序集合。虽然成员是唯一的,但分数值可以重复。
1.3 典型的NoSQL数据库
- 关系型数据库:是指采用了关系模型来组织数据的数据库。标准数据查询语言SQL就是一种基于关系数据库的语言。关系型数据库以行和列的形式存储数据,以便于用户理解。这一系列的行和列被称为表,一组表组成了数据库。用户用查询(Query)来检索数据库中的数据。一个Query是一个用于指定数据库中行和列的SELECT语句。
- NoSQL:“Not Only SQL”的缩写,它的意义是:适用关系型数据库的时候就使用关系型数据库,不适用的时候也没有必要非使用关系型数据库不可,可以考虑使用更加合适的数据存储。
参考:NoSQL数据库的基础知识
2. Redis命令
Redis命令用于在Redis服务器上执行一些操作。
要在Redis服务器上运行命令,需要一个Redis客户端。下面介绍在windows的cmd中的使用,安装配置不再介绍,在Linux中类似。
Redis连接命令
编号 | 命令 | 描述 |
---|---|---|
1 | redis-cli | 连接到本地Redis服务器 |
2 | redis-cli -h host -p port -a password | 该命令用于连接到Redis远程服务器,比如在主机(host)127.0.0.1,端口(port)6379上运行redis服务器,没有密码:redis-cli -h 127.0.0.1 -p 6379 |
3 | ping | 该命令检查服务器是否正在运行 |
4 | AUTH password | 使用给定的密码验证服务器 |
5 | quit或exit | 关闭当前连接 |
6 | SELECT index | 更改当前连接的所选数据库 |
键命令
用于管理Redis中的键
编号 | 命令 | 描述 |
---|---|---|
1 | DEL key | 此命令删除一个指定键(如果存在)。 |
2 | DUMP key | 此命令返回存储在指定键的值的序列化版本。 |
3 | EXISTS key | 此命令检查键是否存在。 |
4 | EXPIRE key seconds | 设置键在指定时间秒数之后到期/过期。 |
5 | EXPIREAT key timestamp | 设置在指定时间戳之后键到期/过期。这里的时间是Unix时间戳格式。 |
6 | PEXPIRE key milliseconds | 设置键的到期时间(以毫秒为单位)。 |
7 | TYPE key | 返回存储在键中的值的数据类型。 |
8 | KEYS pattern | 查找与指定模式匹配的所有键。 |
9 | MOVE key db | 将键移动到另一个数据库。 |
10 | PERSIST key | 删除指定键的过期时间,得永生。 |
11 | PTTL key | 获取键的剩余到期时间。 |
12 | RANDOMKEY | 从Redis返回一个随机的键。 |
13 | RENAME key newkey | 更改键的名称。 |
14 | SORT key [BY pattern] [LIMIT offset count] [ASC | DESC] [ALPHA] |
其中,KEYS pattern
的用法:
h?llo matches hello, hallo and hxllo
h*llo matches hllo and heeeello
h[ae]llo matches hello and hallo, but not hillo
h[^e]llo matches hallo, hbllo, ... but not hello
h[a-b]llo matches hallo and hbllo
Use to escape special characters if you want to match them verbatim.
Redis字符串命令
编号 | 命令 | 描述 |
---|---|---|
1 | SET key value | 此命令设置指定键的值。 |
2 | GET key | 获取指定键的值。 |
3 | GETRANGE key start end | 获取存储在键上的字符串的子字符串。 |
4 | GETSET key value | 设置键的字符串值并返回其旧值。 |
5 | APPEND key value | 将指定值附加到键 |
6 | MGET key1 [key2..] | 获取所有给定键的值 |
7 | SETBIT key offset value | 存储在键上的字符串值中设置或清除偏移处的位 |
8 | SETEX key seconds value | 使用键和到期时间来设置值 |
9 | SETNX key value | 设置键的值,仅当键不存在时 |
10 | SETRANGE key offset value | 在指定偏移处开始的键处覆盖字符串的一部分 |
11 | STRLEN key | 获取存储在键中的值的长度 |
12 | MSET key value [key value …] | 为多个键分别设置它们的值 |
13 | MSETNX key value [key value …] | 为多个键分别设置它们的值,仅当键不存在时 |
14 | PSETEX key milliseconds value | 设置键的值和到期时间(以毫秒为单位) |
15 | INCR key | 将键的整数值增加1 |
16 | INCRBY key increment | |
17 | INCRBYFLOAT key increment | 将键的浮点值按给定的数值增加 |
18 | DECR key | 将键的整数值减1 |
19 | DECRBY key decrement | 按给定数值减少键的整数值 |
Redis 哈希(Hashes)命令(完美用于表示对象)
编号 | 命令 | 描述 |
---|---|---|
1 | HDEL key field2 [field2] | 删除一个或多个哈希字段。 |
2 | HEXISTS key field | 判断是否存在散列字段。 |
3 | HGET key field | 获取存储在指定键的哈希字段的值。 |
4 | HGETALL key | 获取存储在指定键的哈希中的所有字段和值 |
5 | HINCRBY key field increment | 将哈希字段的整数值按给定数字增加 |
6 | HINCRBYFLOAT key field increment | 将哈希字段的浮点值按给定数值增加 |
7 | HKEYS key | 获取哈希中的所有字段 |
8 | HLEN key 获取散列中的字段数量 | |
9 | HMGET key field1 [field2] | 获取所有给定哈希字段的值 |
10 | HMSET key field1 value1 [field2 value2 ] | 为多个哈希字段分别设置它们的值 |
11 | HSET key field value 设置散列字段的字符串值 | |
12 | HSETNX key field value | 仅当字段不存在时,才设置散列字段的值 |
13 | HVALS key | 获取哈希中的所有值 |
Redis列表(Lists)命令
编号 | 命令 | 描述 |
---|---|---|
1 | BLPOP key1 [key2 ] timeout | 删除并获取列表中的第一个元素,或阻塞,直到有一个元素可用,即若有元素,则立即返回,若无元素,则阻塞等待,一旦有新的数据出现在列表中,则立即返回,最大阻塞时间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 | 从列表中获取一系列元素,从0开始,-1表示最后一个元素,-2表示倒数第二个 |
11 | LREM key count value | 从列表中删除元素 |
12 | LSET key index value | 通过索引在列表中设置元素的值 |
13 | LTRIM key start stop | 只保留列表的指定范围元素 |
14 | RPOP key | 删除并获取列表中的最后一个元素 |
15 | RPOPLPUSH source destination | 删除列表中的最后一个元素,将其附加到另一个列表并返回 |
16 | RPUSH key value1 [value2] | 将一个或多个值附加到列表 |
17 | RPUSHX key value | 仅当列表存在时才将值附加到列表 |
Redis集合(Sets)命令
编号 | 命令 | 描述 |
---|---|---|
1 | SADD key member1 [member2] | 将一个或多个成员添加到集合 |
2 | SCARD key | 获取集合中的成员数 |
3 | SDIFF key1 [key2] | 减去多个集合 |
4 | SDIFFSTORE destination key1 [key2] | 减去多个集并将结果集存储在键中 |
5 | SINTER key1 [key2] | 相交多个集合 |
6 | SINTERSTORE destination key1 [key2] | 相交多个集合并将结果集存储在键中 |
7 | SISMEMBER key member | 判断确定给定值是否是集合的成员 |
8 | SMOVE source destination member | 将成员从一个集合移动到另一个集合 |
9 | SPOP key | 从集合中删除并返回成员 |
10 | SRANDMEMBER key [count] | 从集合中获取一个或多个随机成员 |
11 | SREM key member1 [member2] | 从集合中删除一个或多个成员 |
12 | SUNION key1 [key2] | 相并多个集合 |
13 | SUNIONSTORE destination key1 [key2] | 添加多个集并将结果集存储在键中 |
14 | SSCAN key cursor [MATCH pattern] [COUNT count] | 递增地迭代集合中的元素 |
Redis有序集合(Sorted Sets)命令
采用java.util.LinkedHashSet实现的有序集合,如果score不同,则score大的元素大;如果score相同,则字符串字典顺序大的元素大,不能存在一样大的元素,因为有序集合也是集合。
编号 | 命令 | 描述 |
---|---|---|
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] | 迭代有序集合中的元素(包括元素成员和元素分值) |
ZLEXCOUNT
实例:
redis> ZADD myzset 0 a 0 b 0 c 0 d 0 e
(integer) 5
redis> ZADD myzset 0 f 0 g
(integer) 2
redis> ZLEXCOUNT myzset - +
(integer) 7
redis> ZLEXCOUNT myzset [b [f
(integer) 5
Redis HyperLogLog命令
Redis HyperLogLog是一种使用随机化的算法,以少量内存提供集合中唯一元素数量的近似值。比如 {‘apple’, ‘banana’, ‘cherry’, ‘banana’, ‘apple’} 基数为3
优点:即使输入元素的数量或者体积非常非常大,计算基数所需的空间总是固定的12 KB 内存。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
缺点:只会根据输入元素来计算基数,并且会有少许的误差。
编号 | 命令 | 描述 |
---|---|---|
1 | PFADD key element [element …] | 将指定的元素添加到指定的HyperLogLog 中。 |
2 | PFCOUNT key [key …] | 返回给定 HyperLogLog 的基数估算值。 |
3 | PFMERGE destkey sourcekey [sourcekey …] | 将多个 HyperLogLog 合并为一个 HyperLogLog |
Redis发送订阅
发送者(发布者)不是计划发送消息给特定的接收者(订阅者)。而是发布的消息分到不同的频道,不需要知道什么样的订阅者订阅。订阅者对一个或多个频道感兴趣,只需接收感兴趣的消息,不需要知道什么样的发布者发布的。这种发布者和订阅者的解耦合可以带来更大的扩展性和更加动态的网络拓扑。
http://www.redis.cn/topics/pubsub.html
Redis事务
事务可以一次执行多个命令, 并且带有以下两个重要的保证:
- 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
- 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
http://www.redis.cn/topics/transactions.html
管道Pipelining
过去:客户端向服务端发送一个查询请求,并监听Socket返回,通常是以阻塞模式,等待服务端响应
现在:在旧的请求还未响应前,新的请求也能发送到服务器并处理。这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复。
http://www.redis.cn/topics/pipelining.html
Redis Lua 脚本
功能强大,可以实现事务,管道等功能。并且读取延时更小。
http://www.redis.cn/commands/eval.html
将Redis当做使用LRU算法的缓存来使用
http://www.redis.cn/topics/lru-cache.html
大量插入数据
http://www.redis.cn/topics/mass-insert.html
分区(Partitioning):如何将你的数据分布在多个Redis里面
分区是将数据拆分为多个Redis实例的过程,因此每个实例只包含一部分键。
分区的优点:
它允许更大的数据库,使用更多计算机的内存总和。如果没有分区,则限制为单个计算机可以支持的内存量。
它允许将计算能力扩展到多个核心和多个计算机,并将网络带宽扩展到多个计算机和网络适配器。
缺点:操作更加复杂
分区类型
Redis中有两种类型的分区。假设有四个Redis实例:R0,R1,R2,R3以许多代表用户的键,如user:1,user:2,…等等。
范围分区
范围分区通过将对象的范围映射到特定的Redis实例来实现。假设在上面示例中,从ID 0到ID 10000的用户将进入实例R0,而从ID 10001到ID 20000的用户将进入实例R1,以此类推。哈希分区
在这种类型的分区中,使用散列函数(例如,模函数)将键转换成数字,然后将数据存储在不同的Redis实例中。
Redis服务器
编号 | 命令 | 描述 |
---|---|---|
1 | BGREWRITEAOF | 异步重写仅追加的文件 |
2 | BGSAVE | 将数据集异步保存到磁盘 |
3 | CLIENT KILL [ip:port] [ID client-id] | 杀死或断开指定的客户端的连接 |
4 | CLIENT LIST | 获取到服务器的客户端连接列表 |
5 | CLIENT GETNAME | 获取当前连接的名称 |
6 | CLIENT PAUSE timeout | 在指定时间内停止处理来自客户端的命令 |
7 | CLIENT SETNAME connection-name | 设置当前连接名称 |
8 | CLUSTER SLOTS | 获取群集插槽到节点映射的数组 |
9 | 获取Redis命令详细信息的数组 | |
10 | 获取Redis命令的总数 | |
11 | 提取键给出一个完整的Redis的命令 | |
12 | BGSAVE | 将数据集异步保存到磁盘 |
13 | 获取特定Redis命令详细信息的数组 | |
14 | CONFIG GET parameter | 获取配置参数的值 |
15 | CONFIG REWRITE | 使用内存中配置来重写配置文件 |
16 | CONFIG SET parameter value | 将配置参数设置为给定值 |
17 | CONFIG RESETSTAT | 重置由INFO返回的统计信息 |
18 | DBSIZE | 返回所选数据库中的键数量 |
19 | DEBUG OBJECT key | 获取有关键的调试信息 |
20 | DEBUG SEGFAULT | 使服务器崩溃 |
21 | FLUSHALL | 从所有数据库中删除所有键 |
22 | FLUSHDB | 删除当前数据库中的所有键 |
23 | INFO [section] | 获取有关服务器的信息和统计信息 |
24 | LASTSAVE | 获取上次成功保存到磁盘的UNIX时间戳 |
25 | MONITOR | 监听服务器实时接收的所有请求 |
26 | ROLE | 返回实例在复制上下文中的角色 |
27 | SAVE | 将数据集同步保存到磁盘 |
28 | SHUTDOWN [NOSAVE] [SAVE] | 将数据集同步保存到磁盘,然后关闭服务器 |
29 | SLAVEOF host port | 使服务器成为另一个实例的从属,或将其提升作为主服务器 |
30 | SLOWLOG subcommand [argument] | 管理Redis慢查询日志 |
31 | SYNC | 用于复制的命令 |
32 | TIME | 返回当前服务器的时间 |
3 Java中操作Redis--Jedis
官方API
下面简单介绍:
使用Lists:
jedis.lpush("userList", "James");
jedis.rpop("userList"); //可以使用列表模拟队列(queue)、堆栈(stack),并且支持双向的操作(L或者R)。
List<String> userList = jedis.lrange("userList", 0, -1); //第0个到最后一个
jedis.del("userList");
jedis.lset("userList", 1, "Nick Xu"); //设置位置1处为新值
Long size = jedis.llen("userList"); //返回长度
jedis.ltrim("userList", 1, 2); //进行裁剪,只要第1和2个数据
使用Sets:和列表不同,集合中的元素是无序的,因此元素也不能重复。
jedis.sadd("fruit", "apple");
jedis.sadd("fruit", "pear", "watermelon"); //添加到set,可一次添加多个,即这一种
Set<String> fruit = jedis.smembers("fruit"); //遍历集合
jedis.srem("fruit", "pear"); //移除元素:remove
Long size = jedis.scard("fruit"); //返回长度
Boolean isMember = jedis.sismember("fruit", "pear"); //是否包含
jedis.sadd("food", "bread", "milk");
Set<String> fruitFood = jedis.sunion("fruit", "food"); //集合的操作:包括集合的交运算(sinter)、差集(sdiff)、并集(sunion)
使用Sorted Sets:有序集合在集合的基础上,增加了一个用于排序的参数。
jedis.zadd("user", 22, "James"); //有序集合:根据“第二个参数”进行排序。
jedis.zadd("user", 24, "James"); // 再次添加:元素相同时,更新为当前的权重。
Set<String> user = jedis.zrange("user", 0, -1); // zset的范围:找到从0到-1的所有元素。
使用Hashes:
可以使用HashMap存放数据
Map<String, String> capital = new HashMap<String, String>();
capital.put("shanxi", "xi'an");
...
jedis.hmset("capital", capital);
List<String> cities = jedis.hmget("capital", "shannxi", "shanghai");
其他操作
Set<String> keys = jedis.keys("user.userid.*"); //对key的模糊查询
Boolean isExists = jedis.exists("user.userid.14101"); // 是否存在
jedis.setex("user.userid.14101", 5, "James"); // expire:时间为5s
Long seconds = jedis.ttl("user.userid.14101"); //存活时间(ttl):time to live
jedis.persist("user.userid.14101"); //去掉key的expire设置:不再有失效时间
自增的整型:
jedis.set("amount", 100 + ""); // int类型采用string类型的方式存储
jedis.incr("amount"); //递增或递减:incr()/decr()
jedis.incrBy("amount", 20); // 增加或减少:incrBy()/decrBy()
数据清空:
jedis.flushDB(); //清空当前db
jedis.flushAll();// 清空所有db
redis下的db:
redis默认有db0~db15,总共16个数据库,数据库之间通过整数索引标识,而不是由一个数据库名称。默认情况下,一个客户端连接到数据库0。redis配置文件中下面的参数来控制数据库总数:
databases 16
可以通过下面的命令来切换到不同的数据库下
redis>select 2
随后,所有的命令将使用数据库2,直到你明确的切换到另一个数据库下。每个数据库都有属于自己的空间,不必担心之间的key冲突。
事务支持:
Transaction tx = jedis.multi(); //获取事务
for(int i = 0;i < 10;i ++) { //批量操作:tx采用和jedis一致的API接口
tx.set("key" + i, "value" + i);
System.out.println("--------key" + i);
Thread.sleep(1000);
}
List<Object> results = tx.exec(); //执行事务:针对每一个操作,返回其执行的结果,成功即为Ok