Redis-内存数据库、NoSQL数据库、键值数据库
命令行启动服务器:如果是解压版的进入解压路径下 执行 redis-server
关闭服务器可以直接关闭窗口或者 ctrl + c 也可以设置后台进程
命令行启动客户端:如果是解压版的进入解压路径下 执行 redis-cli
String -> 字符串
List -> 队列,栈
Set -> 无序集合
ZSet -> 有序集合
Hash -> hash表结构
这里需要注意的:redis是键值数据库,但是这些数据结构全部指的是值的数据结构,键全部为字符串类型。
simple dynamic string 简化的动态的字符串,可扩展的字符串,类似于java中的StringBuffer
如何扩容:在容量满了会自动扩容, 在容量小于 1M 时,每次翻倍。超过 1M 每次只增加 1M,最多512M
set key value 存储 value 为字符串类型的数据
mset 一次存储多个键值对
mget 一次根据多个键取多个值
清除控制台的操作 clear
expire 设置超时时间 格式如下 expire key 超时时间(秒)
ttl 查看某个 key 剩余的超时时间
如果 返回结果为 -2 表示 当前key 过期
set [ex] [nx] 后可以跟两个可选参数
其中 nx 含义是,不存在key时,set操作才会成功,如果key有了,set操作会返回nil(不会覆盖原有的key)
使用场景:可以用于实现 redis 的分布式锁
incr 对于 value 是数字时,每次自增1
incrby n 对于 value 是数字时,每次自增n
lpush 从左边向list中添加值 格式 lpush key values...
rpush 从右边向list中添加值
lrange 查看list中的值 格式 lrange key start(起始下标) stop(结束下标 如果不知道可以使用-1)
lpop 从list左侧弹(取)值
rpop 从list右侧弹(取)值
既可以当作zhan栈使用也可以当做队列使用
当做栈(先进后出 FILO)
lpush + lpop
rpush + rpop
当队列(先进先出 FIFO)
rpush + lpop
lpush + rpop
llen 查看集合的长度
ltrim 对列表进行截取,格式 key start(起始下标) stop(结束下标)
lindex 按下标获取元素 格式: lindex key index(元素下标) 但是由于list底层是链表所以利用下标取值效率过低
list底层数据结构
ziplist --> 当list中数据量很少时,数据连续存储,访问效率高
quicklist --> 当list 中数据量多时,是一个双向链表,空间利用率高
应用场景:抢购 例如秒杀案例中可以利用redis中的list 保证高效率
也有很多人利用redis 做消息队列,但是这样做不可靠
set集合利用key值保证元素的唯一性,但是set元素无序,zset元素有序
sadd 向set集合中添加元素 格式 sadd key 元素
smembers 查看所有元素 格式 smembers key
sismember 判断元素是否包含在集合中,包含返回1,不包含返回0 格式 sismember key 待测试的元素
scard 获取集合大小 格式 scard key
spop 随机找一个元素移除
数据结构:跳跃表(多层的链表结构,减少比较次数)
zadd 向zset集合中添加元素 格式 zadd key score 元素 注意默认得分低的排在前面
zrange 从zet集合中取元素 格式 zrange key start(起始下标) stop(结束下标)
zrevrange 从zet集合中取元素与 zrange 取出方式相反 格式 zrevrange key start(起始下标) stop(结束下标)
zcard 查看zset集合大小 格式 zcard key
zrem 删除集合中的元素 格式zrem key
数据结构:hash 表(数组+链表)
对比:java中的HashMap的扩容由两个因素决定 一个是初始化容量,负载因子,当map中键值对个数大于 (初始容量 * 负载因子)时会发生扩容。
redis中的Hash采用的是渐进式扩容,扩容过程中会查询新旧两个hash表,不会影响客户的使用,扩容结束才用新的hash表替换掉旧的hash表。
hset 向 hash 表中存入键值 格式 hset key 子key value
hget 从 hash 表中根据键找值 格式 hget key 子key
hgetall 根据键获取此键下所有的键值对 格式 hegetall key
hlen 查看 hash 表中有几组属性 格式 hlen key
hincrby 在 hash 表中对于 value 是数字的 value 值每次自增n 格式 hincrby key 子key(value是数字的)n
hash 结构可以把一些相关的子 key 集中在一起统一管理, 可以对其中属性进行独立处理,但是比字符串要耗费空间。
del 根据 key 删除
flushall 清空整个 redis,删除所有的 key
keys 匹配关键字 根据匹配关键字,查找所有符合的key
slaveof host(要设置为主库的主机号) 将当前redis设置为主机为host的从库
slaveof no one 取消从库设置
RDB:内存快照 (fork 子进程,读写分离)
save 会暂停其他客户端的使用
bgsave 不会影响(暂停)其他客户端的使用, bgsave 会fork 子进程进行快照操作,fork 子进程 - 子进程与主进程共享内存, 子进程负责将快照内容写入磁盘,主进程负责响应客户端指令, 他俩是并行执行的
AOF:将指令记录下来,存储在磁盘上
默认没有启用 通过appendonly = yes 启用,把所有增、删、改相关的命令及数据存入 aof 文件,如果发生宕机,会把aof中的命令从新执行一遍恢复数据。
导入依赖jar包
redis.clients
jedis
3.0.1
org.springframework.boot
spring-boot-configuration-processor
使用JedisPool连接池
将连接池对象交给springBoot管理
@Autowired
private RedisConfig redisConfig;
@Bean
public JedisPool pool() {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(redisConfig.getMaxTotal());//设置最大连接数
config.setMinIdle(redisConfig.getMinIdle());//设置空闲最小链接
JedisPool pool = new JedisPool(config, redisConfig.getHost());
return pool;
}
这里面将配置连接池配置全部配置在springboot配置文件中,利用springboot注解注入到配置类RedisConfig中
@Component
@ConfigurationProperties(prefix = "redis")//读取配置文件中以redis开头的
public class RedisConfig {
private int maxTotal;
private int minIdle;
private String host;
public int getMaxTotal() {
return maxTotal;
}
public void setMaxTotal(int maxTotal) {
this.maxTotal = maxTotal;
}
public int getMinIdle() {
return minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
}
application.properties文件
redis.maxTotal=10
redis.minIdle=1
redis.host=localhost
将java对象存入redis数据库
//注入JedisPool 对象
@Autowired
private JedisPool pool;
@RequestMapping("/setUserToRedis")
@ResponseBody
public String setjson() throws JsonProcessingException {
User user = new User();
user.setName("lisi");
user.setAge(18);
user.setSex("男");
// 利用ObjectMapper 将 java 对象转化为 json 字符串
ObjectMapper om = new ObjectMapper();
String json = om.writeValueAsString(user);
// 使用连接池 将json 存入 redis
try (Jedis jedis = pool.getResource()) {
jedis.set("user", json);
}
return "OK";
}
redis存储如下图
从 redis 中读出数据转化为java对象
@RequestMapping("/getUserFromRedis")
@ResponseBody
public String get() throws IOException {
try (Jedis jedis = pool.getResource()) {
// 从 redis 读取 json字符串
String json = jedis.get("user");
// 利用 ObjectMapper 将 json 转为 java 对象
ObjectMapper om = new ObjectMapper();
User user = om.readValue(json, User.class);
System.out.println(user);
}
return "OK";
}
控制台正常输出:User(name=lisi, age=18, sex=男)
从application.properties 配置文件中读取数据的方式除了利用@ConfigurationProperties注解 还可以利用@Value(EL表达式)
@Value("${redis.maxTotal}")
private int maxTotal;
@Value("${redis.minIdle}")
private int minIdle;
@Value("${redis.host}")
private String host;
这样对应的属性就可以读取到配置文件中的值并注入了