Redis
1. 概念
1.1 特点
Redis 是一款高性能的 NoSQL 系列的非关系型数据库,使用C语言编写.
Redis 是一个key-value存储系统,它支持丰富的数据类型,如 String、hash、list、set、sorted set。
Redis 适合的场景主要局限在较小数据量的高性能操作和运算上。
1.2 Redis为什么把所有的数据放在内存中?
为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以 redis 具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘 I/O 速度为严重影响 redis 的性能。如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。
1.3 使用场景
- 缓存(数据查询、新闻内容、商品内容等)
- 聊天室的在线好友列表
- 任务队列。(秒杀、抢购、12306等)
- 排行榜
- 网站访问统计
- 数据过期处理
- 分布式集群架构
2. 下载安装
2.1 下载地址
默认官网:https://redis.io
中文官网:http://www.redis.net.cn/
直接解压使用:
redis.windows.conf:配置文件
redis-cli.exe:redis 的客户端
redis-server.exe:redis 服务器端
3.命令操作
3.1 redis的数据结构:
redis 存储的是:key,value 格式的数据,其中 key 都是字符串,value 有5种不同的数据结构
-
String - 字符串
String数据结构是简单的 key-value类型,value 不仅可以是 String,也可以是数字。 1. 存储 set key value 127.0.0.1:6379> set username zhangsan OK 2. 获取 get key 127.0.0.1:6379> get username "zhangsan" 3. 删除 del key 127.0.0.1:6379> del username (integer) 1
-
Hash - 字典
在客户端序列化后存储为一个字符串的值(JSON格式) 1. 存储 hset key field value 127.0.0.1:6379> hset myHash username zhangsan (integer) 1 127.0.0.1:6379> hset myHash password 123 (integer) 1 2. 获取 hget key field : 获取指定的 field 对应的值 127.0.0.1:6379> hget hashtest username "zhangsan" hgetall key: 获取所有的 field 和 value 127.0.0.1:6379> hgetall hashtest 1) "username" 2) "zhangsan" 3) "password" 4) "123" 3. 删除 hdel key field 127.0.0.1:6319> hdel hashtest username (integer) 1
-
List - 列表
可以添加一个元素到列表的头部(左边)或者尾部(右边) 1. 添加 lpush key value : 将元素加入列表左边 rpush key value : 将元素加入列表右边 127.0.0.1:6379> lpush myList a (integer) 1 127.0.0.1:6379> lpush myList b (integer) 2 127.0.0.1:6379> rpush myList c (integer) 3 2. 获取 lrange key start end 范围获取 127.0.0.1:6379> lrange myList 0 -1 1) "b" 2) "a" 3) "c" 3. 删除 lpop key 删除列表最左边的元素,并将元素返回 127.0.0.1:6379> lpop myList "b" rpop key 删除列表最右边的元素,并将元素返回 127.0.0.1:6379> rpop myList "c"
-
Set - 集合(不重复)
1. 存储 sadd key value 127.0.0.1:6379> sadd mySet a (integer) 1 127.0.0.1:6379> sadd mySet a (integer) 0 2. 获取 smembers key 127.0.0.1:6379> smembers myset 1) "a" 3. 删除 srem key value 127.0.0.1:6379> srem myset a (integer) 1
-
Sort Set - 有序集合(不重复、有序,每个元素都会关联一个double类型的分数,redis就是通过分数来为集合中的成员实现从小打到大的排序)
1. 存储 zadd key score value 127.0.0.1:6379> zadd mySort 70 Math (integer) 1 127.0.0.1:6379> zadd mySort 92 Chinese (integer) 1 127.0.0.1:6379> zadd mySort 83 English (integer) 1 2. 获取 zrange key start end 127.0.0.1:6379> zrange mySort 0 -1 (integer) 1 1) "Math" 2) "English" 3) "Chinese" 127.0.0.1:6379> zrange mySort 0 -1 withscores (integer) 1 1) "Math" 2) "70" 3) "English" 4) "83" 5) "Chinese" 6) "92" 3. 删除 zrem key value 127.0.0.1:6379> zrem mySort Math (integer) 1
-
通用命令
keys * 查询所有的键 type key 获取键对应的value的类型 del key 删除指定的key value
4.持久化操作
Redis 是一个内存数据库,当 redis 服务器重启或者电脑重启,数据会丢失,我们可以将redis内存中的数据持久化保存到硬盘的文件中。
4.1 RDB 持久化
默认方式,不需要配置,默认使用这种机制。
该机制可以在指定的时间间隔内生成数据集的时间点快照。
在一定的时间间隔中,检测 key 的变化情况,然后持久化数据。
4.1.1 持久化配置
-
编辑 redis.windows.conf 文件
# after 900 sec (15 min) if at least 1 key changed(15 min 至少有1个 key 改变就会持久化一次) save 900 1 # after 300 sec (5 min) if at least 10 keys changed (5 min 至少有10个 key 改变就会持久化一次) save 300 10 # after 60 sec if at least 10000 keys changed (1 min 至少有10000个 key 改变就会持久化一次) save 60 10000
-
重新启动 redis 服务器,并指定配置文件名称
E:\D盘\redis-2.8.9> redis-server.exe redis.windows.conf
这里路径写着是你 redis 放的路径,对应的配置文件
4.1.2 RDB 优缺点
优点:
- RDB 是一个非常紧凑的文件,它保存了 Redis 在某个时间点上的数据集。这种文件适合用于进行备份:你可以设置在指定的时间内,每隔一段时间备份一份 RDB 文件,这样的话,即使遇到问题,也可以随时将数据集还原到不同的版本。
- RDB 非常适用于灾难恢复:只有一个文件,并且内容十分紧凑,可以加密后将它传送到别的数据中心。
- RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。
- RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
缺点
- 如果你需要尽量避免在服务器故障时丢失数据,RDB 就不适合。Redis 允许设置不同的保存点来控制保存 RDB 文件的频率,但是 RDB 文件需要保存整个数据集的状态。一旦出现故障停机,就可能会丢失好几分钟的数据。每次保存 RDB 的时候,Redis 都要 fork() 出一个子进程,并由子进程来进行实际的持久化工作。在数据集比较庞大的时候,fork() 可能会非常耗时,造成服务器会在某一毫秒时刻停止处理客户端;假设数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会达到一秒。
4.2 AOF 持久化
日志记录的方式,可以记录每一条命令的操作。可以每一次命令操作后,持久化数据。
记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。
AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。
Redis 还可以在后台对 AOF 文件进行重写,使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。
4.2.1 持久化配置
-
编辑 redis.windows.conf 文件
appendonly no (关闭AOF) → appendonly yes (开启AOF) appendfsync always : 每一次操作都进行持久化 appendfsync everysec : 每隔一秒进行一次持久化 appendfsync no : 不进行持久化
4.2.2 AOF 优缺点
优点
- 使用 AOF 持久化会让 Redis 变得非常耐久:可以设置不同的 fsync 策略,AOF 的默认策略为每秒钟 fsync 一次,在这种配置下, Redis 仍然可以保持良好的性能。AOF 文件只是一个只进行追加操作的日志文件,因此对 AOF 文件的写入不需要进行进行 seek ,即使日志因为某些原因而包含了未写入完整的命令(比如写入是磁盘已满,写入中途停机),redis-check-aof 工具也可以轻易的修复这种问题。
- Redis 在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写:重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
缺点
- 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB。在一般情况下,每秒 fsync 的性能依然非常高,而关闭 fsync 可以让 AOF 的速度和 RDB 一样快,即使在高负荷下也一样。不过在处理巨大的写入加载时,RDB 可以提供更有保证的最大延迟时间。
4.3 AOF 和 RDB
同时应用 AOF 和 RDB :当redis重启时,他会优先使用 AOF 文件来还原数据集,因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。
5.使用Java客户端操作Jedis
Jedis:一款 Java 操作 redis 数据库的工具。
5.1 下载使用
使用步骤:
1.下载 jedis 工具包(网上都有)
2.使用
// 1.获取连接
// 这里说下,如果使用空参构造,它默认就是 "localhost",6379 端口
Jedis jedis = new Jedis("localhost",6379);
// 2.操作
jedis.set("username",zhangsan);
// 3.关闭操作
jedis.close();
5.2 Jedis 操作各种 redis 中的数据结构
-
字符串类型 String
jedis.set("username","zhangsan"); // 存储 jedis.get("username"); // 获取
-
哈希类型 hash : map 格式
jedis.hset("user","username","zhangsan"); // 存储 jedis.hset("user","age","18"); // 存储 jedis.hset("user","phone","123456"); // 存储 jedis.hget("user","username") // 获取 Map<String,String> user = jedis.hgetAll("user"); // 获取 hash 的所有 map 中的数据
-
列表类型 list : linkedlist 格式。支持重复元素
jedis.lpush("mylist","a","b","c"); // 从左边存 jedis.rpush("mylist","a","b","c"); // 从右边存 jedis.lpop("mylist"); // c jedis.rpop("mylist"); // c List<String> mylist = jedis.lrange("mylist", 0, -1); // 范围获取
-
集合类型 set : 不允许重复元素
jedis.sadd("myset","Math","Chinese","English"); // 存储 Set<String> myset = jedis.smembers("myset"); // 获取
-
有序集合类型 sortedset : 不允许重复元素,且元素有顺序
jedis.zadd("mysortedset",70,"Math"); // 存储 jedis.zadd("mysortedset",83,"Chinese"); // 存储 jedis.zadd("mysortedset",90,"English"); // 存储 Set<String> mysortedset = jedis.zrange("mysortedset",0,-1); // 范围获取
5.3 Jedis 连接池 JedisPool
使用
创建 JedisPool 连接池对象
调用方法 getResource() 方法获取 Jedis 连接
// 创建一个配置对象
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(50); // 最大允许连接数
config.setMaxIdle(10); // 最大空闲连接
// 创建 Jedis 连接池对象
JedisPool jedisPool = new JedisPool(config,"localhost",6379);
// 获取连接
Jedis jedis = jedisPool.getResource();
// 使用
jedis.set("user","zhangsan");
// 关闭,归还到连接池中
jedis.close();
连接池工具类
public class JedisPoolUtils {
private static JedisPool jedisPool;
static{
//读取配置文件
InputStream is = JedisPoolUtils.class.getClassLoader().
getResourceAsStream("jedis.properties");
//创建Properties对象
Properties pro = new Properties();
//关联文件
try {
pro.load(is);
} catch (IOException e) {
e.printStackTrace();
}
//获取数据,设置到JedisPoolConfig中
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));
config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle")));
//初始化JedisPool
jedisPool = new JedisPool(config,
pro.getProperty("host"),Integer.parseInt(pro.getProperty("port")));
}
/**
* 获取连接方法
*/
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
jedis.properties配置文件
host=127.0.0.1
port=6379
maxTotal=50
maxIdle=10