Nosql
1 为什么要用Nosql
-
单机性能不够
-
垂直拆分--高速缓存
-
水平拆分--服务器集群
-
-
not only sql
-
泛指非关系性数据库
-
方便扩展(key,value)
-
大数据量,高性能
-
数据类型多样,不需要设计数据模式
-
2 NoSQL的四大分类
-
kv键值对
-
redis
-
tair
-
Memocache
-
-
文档形数据库
-
MongoDB(处理文档)
-
ConthDB
-
-
图关系型数据库
-
列存储数据库
Redis入门
Remote Dictionary Server
1 能做什么
-
内存存储,持久化存储
-
效率高,可以用于高速缓存
-
发布订阅系统
-
地图信息分析
-
计时器、计数器
2 特性
-
数据类型多样
-
持久化
-
集群
-
事务
3 开始
-
redis-server
-
redis-cli -p 6379
-
shutdown
-
redis-benchmark 测试性能,后面可带参数(并发数等)
4 基础命令
-
redis默认有16个数据库,默认使用第0个。
-
select 切换数据库
-
set key value 添加一条记录
-
Keys * 查看当前数据库所有key
-
dbsize 查看数据库大小
-
Flushdb 清空当前数据库的keys
-
flushall 清除全部数据库数据
-
EXISTS key 判断是否存在
-
Move key 1 移除记录
-
EXPIRE key 10 设置过期时间,单位是秒
-
ttl key 查看当前key的剩余时间
-
type key 查看类型
5 重要知识
-
redis是单线程的。redis是基于内存操作的,cpu不是redis性能瓶颈。
-
数据全部放在内存中,没有上下文切换,速度很快。
Redis数据类型
1. String
String类型是二进制安全的,意思是 redis 的 string 可以包含任何数据。如数字,字符串,jpg图片或者序列化的对象。
-
APPEND key "xxx" 增加一串字符
-
STRLEN key 获取字符串长度
-
Incr key 加一操作
-
decr key 减一
-
GETRANGE key 1 3 获取从一到三的字串
-
SETRANGE key 1 xx 更改字串
-
setex 设置过期时间
-
setnx 如果不存key才设置(分布式锁)
-
mset 批量操作,是原子性的
-
mget
-
mset user:1:name zhangsan user:1:age2
-
Getset
2. List
实际是一个链表,两边插入或改动效率较高,中间效率会低一些。
-
在redis里面可以将list实现成栈,队列等。
-
LPUSH list value
-
LRANGE list 0 -1 显示list中所有元素
-
LRANGE list 0 1 显示指定范围元素
-
RPUSH value 添加到最下面
-
LPOP
-
RPOP
-
lindex list 1 获取第一个值(最下面)
-
Llenth list 获取list长度
-
Lrem list 1 one 移除一个值为one的
-
LTRIM list 1 2 截断,1之前2之后的元素都没了
-
RPUSHLPOP list1 list2 移除列表中最后一个元素并且移动到新的列表中
-
LSET list 1 value 更改1号元素的值
-
LINSERT list before "value1" "value2"在value1前面插入value2
-
LINSERT list after
3. SET
-
sadd myset "hello"; 添加元素
-
sismember myset hello; 确认是否存在
-
smenbers myset 返回所有元素
-
srem myset hello 删除元素
-
srandmember 随机选择一个元素
-
spop myset 随机删除一些set集合中的元素
-
smove set1 set2 移动元素
-
SDIFF set1 set2 差集 set1-set2
-
sinter set1 set2 交集
-
sunion set1 set2 并集
4. Hash
Map集合,存储<key,value>
-
Set myhash key value
-
hmset myhash key1 value1 key2 value2
-
hmget myhash key1 key2
-
hgetall myhash
-
hdel myhash key1
-
hlen myhash
-
hexists myhash key1 判断是否存在
-
hkeys myhash 只获得所有keys
-
hvals myhash 只获得所有value
-
hincrby myhash key 1 增一
-
hsetnx myhash key1 hello 如果不存在可以设置
5. Zset(有序集合)
-
zadd myset 1 one
特殊数据类型
1. geospatial
地理位置数据
-
geoadd mygeo 经度 纬度 名称
-
geodist 计算距离
-
georadius 计算半径内地点
2. hyperloglog
基数统计,类似set,性能更高,可能有错误率但很小
占用内存固定
3. BitMap
所有操作二进制位来进行记录,就只有0和1两个状态
事务
-
redis单条命令不保证原子性
-
没有隔离级别的概念
执行顺序
-
开启事务 multi,后面的命令就在事务中了
-
命令入队
-
执行事务 exec
-
放弃事务 discard
正常执行事务
multi
set k1 v1
set k2 v2
get k2
set k3 v3
exec
编译型异常:所有事务不会执行
运行时异常:1/0 如果事务队列中存在语法性错误,那么执行命令的时候,其他命令是可以正常执行的,错误命令抛出异常!
悲观锁
-
无论做什么都加锁
乐观锁
-
watch 监视对象
-
如果其他线程修改了watch的对象,提交事务执行就会出错,不能执行成功
-
unwatch 解锁
-
执行时比较刚监视的时候的值,如果有改变就执行失败
Jedis
SpringBoot 采用lettuce,使用netty连接,线程安全。
Jedis jedis = new Jedis("127.0.0.1",6379);
jedis.set("name","nanxi");
Transaction transaction = jedis.multi();
try{
transaction.set("name","abc");
transaction.exec();
}catch (Exception e){
transaction.discard();
}finally {
System.out.println(jedis.get("name"));
}
SpringBoot
RedisTemplate redistemplate;
redisTemplate opsForList;
lettuce传输数据会序列化
// 存储java对象,序列化
// 配置自定义序列化方法,默认jdk序列化会传输乱码
Student student = new Student();
student.setId(9527L);
student.setName("nanxi");
student.setAge(22);
student.setEmail("213183396@seu.edu.cn");
String jsonStudent = new ObjectMapper().writeValueAsString(student);
redisTemplate.opsForValue().set("student",jsonStudent);
redisTemplate.opsForValue().set(key,value);
Set<Object> set1 = new HashSet<>();
Set<Object> set2 = new HashSet<>();
//redis事务
Jedis jedis = new Jedis("127.0.0.1",6379);
jedis.set("name","nanxi");
Transaction transaction = jedis.multi();
try{
transaction.set("name","abc");
transaction.exec();
}catch (Exception e){
transaction.discard();
}finally {
System.out.println(jedis.get("name"));
}
Redis.conf
-
配置文件unit单位对大小不敏感。
-
可以包含多个配置文件+路径
-
网络配置
-
IP
-
端口号
-
受保护模式
-
daemonize no 以守护进程方式运行,终端窗口关闭就退出了
-
loglevel notice 日志通知,notice表示日志级别,还有debug、verhouse、warning
-
logfile 日志文件名
-
databases 16 数据库数量默认16个
-
-
快照
持久化,在规定时间内,执行了多少次操作,则会持久化到文件.rdb.aof
-
save 900 1 如果900秒内至少有一个key进行了修改,就进行持久化操作
-
stop-writes-on-bgsave-error yes 持久化如果出错,是否还需要继续工作!
-
rdbcompression yes 默认开启压缩rdb文件
-
rdbchecksum 保存rdb文件的时候,进行错误的检查校验
-
dir ./ rdb文件目录
-
-
安全
-
默认没有密码
-
config set requirepass 设置密码
-
auth pass 用密码登陆
-
-
客户端限制
-
最大客户端数 默认1w maxclients
-
maxmemory <byts> 默认最大内存配置,64位系统没有限制内存大小
-
maxmemory-policy noeviction 内存达到上限后的处理策略
1、volatile-lru:只对设置了过期时间的key进行LRU(默认值)
2、allkeys-lru : 删除lru算法的key
3、volatile-random:随机删除即将过期key
4、allkeys-random:随机删除
5、volatile-ttl : 删除即将过期的
6、noeviction : 永不过期,返回错误
-
-
APPEND ONLY
-
appendonly no 默认是不开启aof模式的,使用rdb方式持久化。
-
appendfsync everysec 每秒执行一次同步
-
Redis持久化
RDB(Redis DataBase)
-
save 900 1 如果900秒内至少有一个key进行了修改,就进行持久化操作,生成一个dump.rdb文件。
-
触发机制:
-
save的规则满足的情况下,会自动触发rdb规则。
-
执行flushall命令,也会触发rdb规则
-
退出redis,也会产生rdb文件
-
-
启动就会自动恢复其中的数据
-
优点:适合大规模的数据恢复;对数据一致性要求不高。
缺点:需要一定的时间间隔进程操作,如果redis宕机最后一次数据就没有了,持久化时会开一个子进程,利用内存空间。
AOF (Append Only File)
-
以日志的形式将所有写操作记录下来,需要数据恢复的时候重写就是了,默认是不开启的。
-
如果aof文件有错误,这时候redis是启动不起来的,使用redis-check-aof --fix 修复aof文件。
优点:
-
每一次修改都同步,文件的完整性会更好。
-
每秒同步一次,可能丢失一秒数据
-
从不同步,效率最高的!
缺点:
-
数据文件较大,数据恢复慢
-
运行效率低
-
Redis发布订阅
Redis主从复制
1主多从
-
数据复制是单向的,读写分离
-
数据冗余,故障恢复,负载均衡,高可用基石
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0 #没有从机
master_failover_state:no-failover
master_replid:51e20a80a5cde6f38c457e742fe61c06bed3b3a9
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
可以配置单机多集群,使用不同的配置文件。
slaveof ipadress port
#配置成主机的从机
在配置文件中的配置是永久的配置。
从机不能执行写操作。掉线的从机重连数据会同步。
-
全量复制
-
增量复制
层次模式:主--从--从
slaveof no one 从机变成主机
原主机回来也没用了。
哨兵模式
sentinel.conf 哨兵的配置文件,需要配置它监听的主机。
优点:
-
哨兵集群基于主从复制模式,所有的主从配置优点,有权游。主从可以切换,故障可以转移。更加健壮。
-
redis不好在线扩容,集群数量一旦上线,在线扩容就十分麻烦。
-
配置文件
-
端口号
-
sentinel.conf工作目录
-
监视目录。
-
Redis缓存穿透和雪崩
redis缓存中没有的话,请求会到持久层MySQL,请求过多时造成服务器崩掉。
布隆过滤器
布隆过滤器是一种数据结构,对所有可能差选的参数以hash的形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。
缓存空对象
热点数据不过期,设置分布式锁
停掉一些服务,保证主要的服务可用