一、NoSQL概述
1、NoSQL特点
- 方便扩展
- 大数据量高性能
- 数据类型多样性
传统关系型数据库(RDBMS)和非关系型数据库(NoSQL)的区别
传统关系型数据库(RDBMS)
- 结构化组织
- 固定sql语言
- 数据和关系都存在表中
- 严格的一致性
- …
非关系型数据库(NoSQL)
- 不仅仅是数据
- 没有固定的查询语言
- 存储方式多样:键值对、列、文档、图形数据库
- 最终一致性
- 高性能、高可用、高可扩展
- …
2、关系型数据库分类
3、非关系型数据库分类
二、安装与使用Redis
1、Redis启动
-
启动Redis服务:
redis-server usr/local/bin/kconfig/redis.conf(redis根路径)
-
使用Redis客户端连接:
redis-cli -p 6379
-
查看redis进程:
ps -ef|grep redis
-
关闭redis服务:
shutdown、exit
-
重启redis:
systemctl restart redis.service
2、Redis性能测试
redis-benchmark [option] [option value]
3、Redis基础知识
-
默认16个数据库
-
Redis是单线程的
-
Redis是单线程速度却很快的原因:
- 多线程CPU上下文会切换,而redis将数据存储在内存中。对于内存系统来说,单线程效率最高。
-
端口号6379 - MERZ
4、Redis基本命令
-
127.0.0.1:6379> SELECT [index]
切换数据库
-
127.0.0.1:6379> DBSIZE
查看当前数据库键值对长度
-
127.0.0.1:6379> keys *
查看所有key
-
127.0.0.1:6379> FLUSHDB
清除当前数据库内容
-
127.0.0.1:6379> FLUSHALL
清除所有数据库内容
-
127.0.0.1:6379> EXISTS [key]
查看key是否存在(存在显示(integer) 1)
-
127.0.0.1:6379> MOVE [key] [databaseIndex]
移除指定数据库的key
-
127.0.0.1:6379> EXPIRE [key] [second]
设置过期时间
-
127.0.0.1:6379> TTL [key]
查看剩余过期时间
-
127.0.0.1:6379> TYPE [key]
查看key的类型
三、Redis数据类型
1、五大基本数据类型
String字符串
以key-value方式存储
-
127.0.0.1:6379>set [key] [value]
创建键值对,若存在key则覆盖
-
127.0.0.1:6379>get [key]
根据key取出value
-
127.0.0.1:6379> APPEND [key] [String]
字符串后添加字符串
-
127.0.0.1:6379> STRLEN [key]
获取字符串长度
-
127.0.0.1:6379> INCR [key]
+1操作(需要为Integer类型,下同)
-
127.0.0.1:6379> DECR [key]
-1操作
-
127.0.0.1:6379> INCRBY [key] [num]
增加某值
-
127.0.0.1:6379> DECRBY [key] [num]
减少某值
-
127.0.0.1:6379> GETRANGE [key] [begin] [end]
获取字符串区间值
-
127.0.0.1:6379> GETRANGE [key] 0 -1
获取字符串全部值
-
127.0.0.1:6379> SETRANGE [key] [begin] [value]
将从begin开始的位置,替换成value
-
127.0.0.1:6379> SETEX [key] [second] [value]
定义key时设置过期时间
-
127.0.0.1:6379> SETNX [key] [value]
如果key不存在,则设置key(不会覆盖)
-
127.0.0.1:6379> MSET k1 v1 k2 v2 k3 v3
一次性设置多个key value
-
127.0.0.1:6379> MGET k1 k2 k3
一次性取出多个值
-
127.0.0.1:6379> MSETNX k1 v1 k4 v4
如果k1,k4都不存在,设置key value。原子性操作,一起成功或一起失败
-
127.0.0.1:6379> mset user:1:name odinpeng user:1:age 21
创建user对象
-
127.0.0.1:6379> getset [key] [value]
先获取原来的值再设置新值
List列表
以 key-v1 v2 v3方式存储,可重复
-
127.0.0.1:6379> LPUSH [key] [value1]
在key列表中,从前往后插入
-
127.0.0.1:6379> LRANGE [key] [begin] [end]
取出key集合从begin到end索引的值(0 -1取全部)
-
127.0.0.1:6379> RPUSH [key] [value1]
在key列表中,从后往前插入
-
127.0.0.1:6379> LPOP [key]
从左边移除key列表的第一个元素
-
127.0.0.1:6379> RPOP [key]
从右边移除key列表的第一个元素
-
127.0.0.1:6379> LINDEX [key] [index]
获取index索引值
-
127.0.0.1:6379> LLEN [key]
查看key列表长度
-
127.0.0.1:6379> LREM [key] [count] [value]
移除key列表指定个数的value
-
127.0.0.1:6379> LTRIM [list] [begin] [end]
截取指定范围的值,列表已经被修改
-
127.0.0.1:6379> RPOPLPUSH [key] [key1]
移除key最后一个元素到key1中
-
127.0.0.1:6379> LSET [key] [index] [new value]
更新列表index索引的值,不存在此下标会报错
-
127.0.0.1:6379> LINSERT [key] before|after [value] [new value]
在列表指定值前|后插入新值(若有重复value,取第一个value)
Set集合
以key -v1 v2 v3方式存储,不可重复
-
127.0.0.1:6379> SADD [key] [v1] [v2] [v3]
在set集合中添加元素,不可重复,重复覆盖原来元素
-
127.0.0.1:6379> SMEMBERS [key]
查看集合所有元素
-
127.0.0.1:6379> SISMEMBER [key] [value]
查看value是否在key中存在,存在返回1不存在返回0
-
127.0.0.1:6379> SCARD [key]
查看key中有几个元素
-
127.0.0.1:6379> SREM [key] [value]
移除key中的某值
-
127.0.0.1:6379> SRANDMEMBER [key] [count]
随机抽出count个元素
-
127.0.0.1:6379> SPOP [key] [count]
随机移除count个元素
-
127.0.0.1:6379> SMOVE [key1] [key2] [value]
将key1中的值移动到key2中
-
127.0.0.1:6379> SDIFF [key] [key2]
找出key和key2的不同值
-
127.0.0.1:6379> SUNION [key] [key2]
求key和key2的并集
Hash哈希
以 key-<k1,v1>,<k2,v2>,<k3,v3> 方式存储
-
127.0.0.1:6379> HSET [key] [k1] [v1] [k2] [v2]
向key中添加k1 v1和k2 v2键值对
-
127.0.0.1:6379> HGET [key] [k1]
取出key中的k1的值
-
127.0.0.1:6379> HGETALL [key]
显示所有key中的键值对
-
127.0.0.1:6379> HMGET [key] [k1] [k2]
同时取出key中k1和k2的值
-
127.0.0.1:6379> HDEL [key] [k1] [k2]
同时删除key中k1和k2的值
-
127.0.0.1:6379> HLEN [key]
查看当前key中的键值对个数
-
127.0.0.1:6379> HEXISTS [key] [k1]
判断key中的k1是否存在
-
127.0.0.1:6379> HKEYS [key]
获取当前key中的所有键
-
127.0.0.1:6379> HVALS [key]
获取当前key中的所有值
-
127.0.0.1:6379> HINCRBY [key] [k1] [count]
将key中k1对应的值+count,count为负数则为-
-
127.0.0.1:6379> HSETNX [key] [k1] [v1]
若k1存在则创建,k1不存在则不创建
Zset有序集合
以key- <num1,v1>,<num2,v2>,<num3,v3>存储,有序集合
-
127.0.0.1:6379> ZADD [key] [num1] [v1] [num2] [v2] [num3] [v3]
在key中存储带序号的值,保存顺序按照序号从小到大
-
127.0.0.1:6379> ZRANGE [key] [begin] [end]
查看key中从begin到value索引的部分,0 -1查看所有
-
127.0.0.1:6379> ZRANGEBYSCORE [key] [min] [max]
从min到max排列显示value,负无穷-正无穷:-inf +inf
-
127.0.0.1:6379> ZRANGEBYSCORE [key] [min] [max] withscores
从min到max排列显示value、num,负无穷-正无穷:-inf +inf
默认为开区间,在num前添加(将其设置为闭区间。
-
127.0.0.1:6379> ZREVRANGE [key] [begin] [end]
倒序查看从begin到endkey中的value
-
127.0.0.1:6379> ZRANGE [key] [value]
移除key中的value
-
127.0.0.1:6379> ZCARD [key]
获取集合中的个数
-
127.0.0.1:6379> zcount [key] [min] [max]
获取指定区间的个数
2、三种特殊数据类型
Geospatial地理位置
有效纬度:-85.05112878到85.05112878
有效经度:-180到180
-
127.0.0.1:6379> GEOADD [key] 纬度 经度 [place]
在key中添加城市的纬度经度
-
127.0.0.1:6379> GEOPOS [key] [place1] [place2]
获取key中城市的纬度经度
-
127.0.0.1:6379> GEODIST [key] [place1] [place2] [m,km,ft,mi]
获取key中两个位置的距离,默认单位为m
-
127.0.0.1:6379> GEORADIUS [key] [经度] [纬度] [半径] [m,km,ft,mi]
找出key中所有与指定经度纬度位置距离小于半径的地方
-
127.0.0.1:6379> GEORADIUSBYMEMBER [key] [place] [半径] [m,km,ft,mi]
找出key中与place距离小于半径的城市,包括place
Hyperloglog基数统计
存储方式与set类似,但内存较小,用于大数量的数据统计
-
127.0.0.1:6379> PFADD [key] [v1] [v2] [v3]
向key中添加v1 v2 v3,不可重复
-
127.0.0.1:6379> PFCOUNT [key]
获取key中元素数量
-
127.0.0.1:6379> PFMERGE [key] [key1] [key2]
将key1和key2合并为key
Bitmap位图
统计用户信息,适用于只有两个状态(例如打卡为1,未打卡为0)
-
127.0.0.1:6379> SETBIT [key] [num] [0/1]
往key中存储某num和其状态(0或1)
-
127.0.0.1:6379> GETBIT [key] [num]
获取key中num的状态,为1则返回(integer) 1
-
127.0.0.1:6379> BITCOUNT [key]
统计状态为1的总数
四、事物
-
Redis单条命令保证原子性,但事物不保证原子性(同时成功或同时失败)
-
Redis事物没有隔离级别的概念
1、事物基本操作
- 开启事物
- 输入命令
- 提交事务,一次性执行命令
2、基本命令
-
127.0.0.1:6379> MULTI
开启事物
-
127.0.0.1:6379> EXEC
提交事物
-
127.0.0.1:6379> DISCARD
放弃事物
3、出现异常
-
编译时异常,输入命令错误,所有命令都不会执行
-
运行时异常,命令语法正确,运行时报错。除报错命令,其他命令正常执行
4、锁
悲观锁
- 很悲观,认为命令会出问题,无论什么时候都上锁。效率低
乐观锁
-
很乐观,认为命令不会出问题,不会上锁。效率高。
-
获取value
-
更新的时候比较value
Redis监视测试
-
事物正常结束,数据期间没有发生变动,则正常执行成功。
-
事物提交前,另一个线程修改了值,则导致事物失败。
-
127.0.0.1:6379> WATCH [key]
监视某key
-
127.0.0.1:6379> UNWATCH [key]
接触对key的监控
五、Jedis
1、Jedis简介
Jedis是redis的java版本的客户端实现
2、Jedis使用
1、引入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.2.2</version>
</dependency>
2、测试连接(使用本地连接)
import org.junit.Test;
import redis.clients.jedis.Jedis;
public class TestPing {
@Test
public void test1(){
Jedis jedis = new Jedis("127.0.0.1",6379); //ip,端口号
System.out.println(jedis.ping());
}
}
输出结果:
六、SpringBoot整合
在SpringBoot 2.0之后,操作redis由原来的jedis替换成了lettuce
-
jedis:采用直连方式,多线程操作不安全
-
lettuce:采用netty,实例可以在多个线程中进行共享,不存在线程不安全情况
1、使用方式
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置properties文件
#配置redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
- 连接测试
@SpringBootTest
class RedisSpringBootApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
redisTemplate.opsForValue().set("k1","你好!");
Object k1 = redisTemplate.opsForValue().get("k1");
System.out.println(k1);
//获取redis连接对象
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
connection.flushAll();
}
}
操作数据类型
redisTemplate.opsForValue(); //String
redisTemplate.opsForList(); //List
redisTemplate.opsForHash(); //Hash
redisTemplate.opsForSet(); //Set
redisTemplate.opsForZSet(); //ZSet
redisTemplate.opsForGeo(); //Geospatial
redisTemplate.opsForHyperLogLog(); //Hyperloglog
2、具体使用
- 编写Redis配置类,实现序列化
//Redis配置类
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
-
在真实开发中,不会使用原生redisTemplate来写redis命令
-
常常会写一个RedisUtils来封装set、get等方法,直接用RedisUtils.set()写Redis命令
3、Redis设置密码
- 设置密码
127.0.0.1:6379> config set requirepass password
- 查看密码
127.0.0.1:6379> config get requirepass
- 登录
127.0.0.1:6379> AUTH password