Redis是一款**c语言**开发的、采用key-value数据存储格式的内存级NoSQL数据库,重点关注数据存储格式,是key-value格式,也就是键值对的存储形式。与MySQL数据库不同,MySQL数据库有表、有字段、有记录,Redis没有这些东西,就是一个名称对应一个值,并且数据以存储在内存中使用为主。Redis有它的数据持久化方案,分别是RDB和AOF,但是Redis自身并不是为了数据持久化而生的,主要是在内存中保存数据,加速数据访问的,所以说是一款内存级数据库。非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。
redis(键值数据库)、MongoDB(文档型数据库)、HBase(列式数据库)、Cassandra(宽列数据库)、Neo4J(图形数据库)等。
优点:
1. 格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。
2. 速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘。
3. 高扩展性。
4. 成本低:nosql数据库部署简单,基本都是开源软件。
缺点:
1. 不提供sql支持,学习和使用成本较高。
2. 无事务处理。
3. 数据结构相对复杂,复杂查询方面稍欠。
- 数据库
- 缓存
- 任务队列
- 消息队列
- 分布式锁
在官网( https://redis.io/commands )可以查看到所有的命令。
Redis 教程 | 菜鸟教程 (runoob.com)。
使用时不区分大小写。
命令 | 介绍 |
---|---|
KEYS parrern | 查找所有符合给定模式(pattern)的可以。例如:keys * 获取所有的key。 |
EXISTS key | 检查key是否存在 |
TYPE key | 返回key所存储值的类型 |
EXPIRE key | key设置有效期,有效期到期时该key会被自动删除 |
TTL key | 返回key的剩余生存时间,秒为单位。TTL:time to live |
DEL key | 删除存在的key |
命令 | 描述 |
---|---|
SET key value | 添加键值对或修改指定key的值 |
GET key | 获取key的值 |
MSET key1 value1 key2 value2 ... | 批量添加多个键值对 |
MGET key1 key2 ... | 根据多个key获取对应的值 |
INCR key | 指定key的值+1 |
INCRBY key n | 指定key的值+n |
SETNX key value | key不存在时添加 |
SETEX key seconds value | 添加键值对同时为key指定存活时间 |
Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。
string的数据存储是一个名称对应一个值,如果要维护的数据过多,可以使用hash哈希存储模型,它一个名称下可以存储多个数据,每个数据也可以有自己的二级存储名称。
命令 | 描述 |
---|---|
HSET key field value | 添加或修改 |
HGET key field | 获取指定key中filed对应的值 |
HDEL key fileld | 删除指定key中f指定的filed |
HKEYS key | 获取指定key中所有filed |
HVALS key | 获取指定key中所有value |
HGETALL | 获取指定key中所有filed和value |
HSETNX | 指定key中filed不存在时添加 |
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
命令 | 描述 |
---|---|
LPUSH key value1 value2 ... | 左侧插入一个或多个元素 |
LPOP key | 移除并返回列表左侧的第一个元素,没有则返回nil |
RPUSH key value1 value2 ... | 右侧插入一个或多个元素 |
RPOP key | 移除并返回列表右侧的第一个元素,没有则返回nil |
LLEN key | 获取列表长度 |
LRANGE key start stop | 获取指定范围内的元素(0,-1)可以获取所有元素 |
BLPOP key timeout | 移出并获取列表左侧的第一个元素, 如果列表没有元素 会阻塞列表直到等待超时或发现可弹出元素为止 |
BRPOP key timeout | 移出并获取列表右侧的第一个元素, 如果列表没有元素 会阻塞列表直到等待超时或发现可弹出元素为止 |
Redis 的 set 是 string 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
命令 | 描述 |
---|---|
SADD key member1 member2 ... | 向集合添加一个或多个成员 |
SREM key member1 member2 ... | 移除集合中一个或多个成员 |
SMEMBERS key | 返回集合中的所有成员 |
SCARD key | 获取集合的成员数 |
SISMEMBER key member | 判断 member 元素是否是集合 key 的成员 |
SDIFF key1 key2 ... | 返回第一个集合与其他集合之间的差异 |
SINTER key1 key2 ... | 返回给定所有集合的交集 |
SUNION key1 key2 ... | 返回所有给定集合的并集 |
Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
命令 | 描述 |
---|---|
ZADD key score1 member1 score 2member2 ... | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
ZREM key member1 member2 ... | 移除有序集合中的一个或多个成员 |
ZCARD key | 获取有序集合的成员数 |
ZCOUNT key min max | 计算在有序集合中指定区间分数的成员数 |
ZRANGE key start stop | 通过索引区间返回有序集合指定区间内的成员 |
ZSCORE key member | 返回有序集中,成员的分数值 |
ZRANGEBYSCORE key min max | 通过分数返回有序集合指定区间内的成员 |
ZRANK key member | 返回有序集合中指定成员的索引 |
ZREVRANK key memeber | 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 |
注意:所有的排名默认都是升序,如果要降序则在命令的最后面添加REV
升序获取sorted set 中的指定元素的排名:ZRANK key member。
降序获取sorted set 中的指定元素的排名:ZREVRANK key memeber。
- zset:ziplist(压缩列表)或skiplist(跳跃表)。
- 元素数量小于128个,且每个元素长度小于64字节时使用压缩列表,其他情况使用跳跃表。
1.压缩列表:本质是一个数组,数组首部存长度、偏移量、元素个数,尾部存结束标识。每个元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个节点保存元素的分值。
2.跳跃表:单向链表按序保存元素及分值,使用哈希表dict来保存元素和分值的映射关系。链表增加了多级索引,先从最上层索引跳跃查,再渐渐往下层到链表地查询,实现了快速查找元素,时间复杂度O(logn),这种查询算法类似于链表版二分查找,是基于有序的。
zset底层不使用红黑树的原因:
范围查找:因为红黑树范围查找效率低,而跳跃表范围查找效率高,因为是链表结构。zset可以用zrange命令查指定范围内元素。
实现难度:跳跃表实现比红黑树简单。
Spring Data Redis(Spring官网)
Spring Data Redis中提供了一个高度封装的类:RedisTenplate,将同一类型操作封装为operation接口:
1. ValueOperations:操作简单字符串key-value。
2. SetOperations:操作set类型。
3. ZSetOperations:操作sortedSet类型。
4. HashOperations:操作hash类型。
5. ListOperations:操作list类型。
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
创建项目时也可以勾选自动导入redis启动器。
基本配置
spring:
redis:
# redis的ip
host: 192.168.93.128
# redis的端口号
port: 6379
# redis的密码
password: 123456
更多配置
spring:
redis:
host: 192.168.93.128 #redis的ip
port: 6379 #redis的端口号
password: 123456 #redis的密码
database: 0 #操作redis几号库
timeout: 5000 #读取超时时间
connect-timeout: 10000 #连接超时时间
lettuce: #lettuce连接池配置
pool:
enabled: true #开启连接池
max-active: 10 #最大连接数
max-idle: 4 #最大空闲连接
min-idle: 0 #最小空闲连接
max-wait: -1 #最大连接阻塞等待时间,过该时间仍无法获取连接则抛出异常 -1没有限制
time-between-eviction-runs: -1 #关闭空闲时间超过指定时间的连接
@SpringBootTest
class RedisApplicationTests {
@Autowired
RedisTemplate redisTemplate;
@Test
void testString() {
ValueOperations valueOperations = redisTemplate.opsForValue();
valueOperations.set("id", "1");
Object name = valueOperations.get("id");
System.out.println(name);
valueOperations.getAndExpire("id", Duration.ofSeconds(10));
DataType dataType = redisTemplate.type("id");
System.out.println(dataType);
Long l = redisTemplate.getExpire("id");
System.out.println(l);
}
@Test
void testList(){
ListOperations listOperations = redisTemplate.opsForList();
listOperations.leftPush("names", "zs");
listOperations.rightPush("names", "ls");
List list = listOperations.range("names", 0, -1);
System.out.println(list);
}
@Test
void testHash(){
HashOperations hashOperations = redisTemplate.opsForHash();
hashOperations.put("user", "id", "1");
hashOperations.put("user", "name", "ls");
Map
RedisTemplate是以对象为操作的基本单元,存到数据库的实际内容是序列化后的。
@SpringBootTest
class RedisApplicationTests {
@Autowired
RedisTemplate redisTemplate;
@Test
void testString() {
/* 设置key-value 序列化器 */
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
ValueOperations valueOperations = redisTemplate.opsForValue();
valueOperations.set("id", "1");
}
StringRedisTemplate是以字符串为操作的基本单元。命令行客户端redis-cli.exe默认使用StringRedisTemplate。
为了方便使用基于字符串为数据的操作,springboot整合redis时提供了专用的API接口StringRedisTemplate。
RedisTemplate是以对象为操作的基本单元,存到数据库的实际内容是序列化后的。
@SpringBootTest
class RedisApplicationTests {
@Autowired
StringRedisTemplate stringRedisTemplate;
@Test
void testString() {
ValueOperations valueOperations = stringRedisTemplate.opsForValue();
valueOperations.set("sid", "1");
}
@Test
void testList(){
ListOperations listOperations = stringRedisTemplate.opsForList();
listOperations.leftPush("snames", "zs");
listOperations.rightPush("snames", "ls");
}
springboot整合redis技术提供了多种客户端兼容模式,默认提供的是lettucs客户端技术,也可以根据需要切换成指定客户端技术,例如jedis客户端技术。jedis是Redis传统的客户端技术。
org.springframework.boot
spring-boot-starter-data-redis
redis.clients
jedis
基本配置
spring:
redis:
host: 192.168.93.128 #redis的ip
port: 6379 #redis的端口号
password: 123456 #redis的密码
更多配置
spring:
redis:
host: 192.168.93.128 #redis的ip
port: 6379 #redis的端口号
password: 123456 #redis的密码
database: 0 #操作redis几号库
timeout: 5000 #读取超时时间
connect-timeout: 10000 #连接超时时间
jedis: #jedis连接池配置
pool:
enabled: true #开启连接池
max-active: 10 #最大连接数
max-idle: 4 #最大空闲连接
min-idle: 0 #最小空闲连接
max-wait: -1 #最大连接阻塞等待时间,-1表示没有时间限制
time-between-eviction-runs: -1 #关闭空闲时间超过指定时间的连接
lettcus基于Netty框架进行与Redis服务器连接,底层设计中采用StatefulRedisConnection。 StatefulRedisConnection自身是线程安全的,可以保障并发访问安全问题,所以一个连接可以被多线程复用。lettcus也支持多连接实例一起工作。
jedis连接Redis服务器是直连模式,当多线程模式下使用jedis会存在线程安全问题,解决方案可以通过配置连接池使每个连接专用,这样整体性能就大受影响。
redis使用较多的使用场景为缓存。
Spring Cache是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
Spring Cache提供了一层抽象,底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不同的缓存技术。
缓存: 缓存是一种介于数据永久存储介质与应用程序之间的数据临时存储介质,使用缓存可以有效的减少低速数据读取过程的次数(例如磁盘IO),提高系统性能。此外缓存不仅可以用于提高永久性存储介质的数据读取效率,还可以提供临时的数据存储空间。而springboot提供了对市面上几乎所有的缓存技术进行整合的方案。
org.springframework.boot
spring-boot-starter-cache
@SpringBootApplication
//开启缓存功能
@EnableCaching
public class SpringbootCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootCacheApplication.class, args);
}
}
使用@Cacheable注解后,执行当前操作,如果发现对应名称在缓存中没有数据,就正常读取数据,然后放入缓存;如果对应名称在缓存中有数据,就终止当前业务方法执行,直接返回缓存中的数据。
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookMapper bookMapper;
//Cacheable译为可缓存的,可缓冲的。@Cacheable的value属性是存储空间名,key属性是此方法返回值在存储空间内的键名。
//key属性名必须和形参名一样才能缓存,别忘了#号。 多个参数可以使用拼接方式:"#id+'_'+#name"。
@Cacheable(value="BookServiceGetById",key="#id")
public Book getById(Integer id) {
return bookMapper.selectById(id);
}
}
注意:
一定一定别忘了#号。
缓存的key属性名必须方法的形参名一样才能缓存。 只要此key对应的缓存已存在,下次不管查询出什么数据,返回的结果都是直接从缓存的这个key里取。
被注解@Cacheable声明的方法不能被本类中其他方法调用,原因是spring容器管理问题。
org.springframework.boot
spring-boot-starter-cache
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
spring:
redis:
port: 6379
host: 192.168.93.128
password: 123456
cache:
type: redis