键值对数据库
特征
*键值型
*单线程(多线程情况 仅仅在于网络请求)
*低延迟,速度快(基于内存,IO多路复用,)
*支持持久化
*支持集群,分片
*支持多语言
常见的命令
数据结构:
string
hash
list
set
sorteSet
Geo
bitMap
发布/订阅
Keys : 查找符合的key(谨慎使用-会阻塞)
Del :删除
existsx:是否存在
expire:设置有效期
TTL:查看有效时间(-2就是被移除,-1就是永久有效)
string类型
*最大512M,
*底层可以存string int float,底层都是字节 只是编码方式不同。
*int 和 float可以做自增或减
命令:
set(增或改) ,get,mset(批量),mget
*incr: 加1, incr key 整数
*incrby .加N,incrby key 6 减(负数)
*incrbyFloat 增加小数,
*setnx:添加一个string的健值对,前提是key不存在 否则不执行-setnx name zhangsan 返回1成功
*setex:添加一个string的健值对,并设置时长
hash类型
hash计算那个插槽(slot)是根据优先部分计算的(hash_tag)例如 {a}666,{a}777,根据a计算
散列,其value是无序下字典
结构 key-value(field+value)
命令
hset:加或改 ( hset no1 name 张三)
hget:获取(hget no1 name)
hmset
hmget
hgetall 获取所有的键值
hkeys
hvals 获取的一个key的所有值
hincrby 让ket自增长
hsetnx 添加一个hash类型的field值 前提的filed不存在 否则不执行
List类型
类似双向链表,linkList
*有序,可以重复,
*插入和删除快,
*查询速度一般
命令
*lpush:向左插入一个或者多个(头插入)
*rpush:向右插入一个或者多个(尾插入)
*lpop:移除并返回左侧第一个元素 没有就返回nil(取)
*rpop:移除并返回左侧第一个元素 没有就返回
*blpop和brpop,(阻塞)取 没有元素时候指定等待时间,不返回nil
*lrange ket star end 返回范围内的数据(不移除)
可以模拟 栈,队列,阻塞队列
栈:先进后出
队列:先进先出
Set类型
类似hashset 可以看作是值为null的hashMap
*无序
*不重复
*查询快
*支持交集,并集,差集的功能
命令
*sadd key member: 加一个或者多个
*srem key member:移除一个或者多个
*scard key:返回set中元素个数
*smembers:获取set中所有元素
*sinter key1 key2:求连个key的交集
*sdiff:差集
*sunion:并集
Scan:非阻塞,可以获取不到最新的key
Redis 的事务是通过 multi和 exex 命令实现的。
SortSet类型
类似java的TreeSet
*可排序
*不重复
*查询速度快
经常被用于排行榜的功能
命令
*zadd增
*zrem删
*zscore key 获取取值
*zrank 获取排名
*zcard 获取元素个数
*zcount 在范围内计数
*zincrby自增
*zrange 获取排名内的元素
*获取分数值范围的元素
*求交几 差集 并集
*在Z后面加rev就是降序
redis的java客户端
jedis:简单,线程不安全,要创建连接池
lettuce:基于netty框架,支持同步,一般,线程安全,支持redis的哨兵模式 集群模式 管道模式
Redisson:基于redis实现分布式 可以伸缩的Java数据结构入Map queue lock Atomiclong
spring Data redis 整合了 jedis和lettuce
1:jedis
使用步骤:1引入依赖-2创建jedis对象连接,-3使用方法命令-4释放资源
jedis连接池
背景:jedis是线程不安全,频繁创建和消耗对性能消耗很大。
封装并 提供一个放回jedis对象的静态方法
2:SpringDataRedis
特征
*提供了对jedis和lettuce的整合
*提供了redisTemplate统一API操作redis
*支持redis的发布/订阅模型
*支持redis的哨兵和集群模式
*支持lettuce的响应式编程
*支持基于jdk,json,字符串,spring对象的序列化和反序列化(存对象)
*支持基于redis的JDKcollection实现((分布式)重写集合)
封装了redis的各种操作API:(每种数据类型都有)如string list等
使用注意-序列化方案
1序列化和反序列化的类型选择,
1.1(选择json序列化器l为了反序列化会把对象的class写入json中,对redis带来很大额外开销)自动
1.2选择string序列化器,然后手动完成序列化和反序列化操作(使用StringRedisTemplate)手动
StringRedisTemplate对象 string序列化器
操作Hash类型
.put .get
Redission分布式锁,
*可重入锁(对象是自己就可以进入,加入计数器)hash数据类型的方式
基于setnx()锁存在的问题
*不可以重入:同一个线程无法多次获取同一把锁
(对象是自己就可以进入,基于hash结构加入计数器)
*不可以重试:获取锁失败就直接返回,
(加等待时间 ,默认看门狗时间30秒【可以先判断剩余时间和等待时间大小,订阅别人释放锁,再重试】)等待, 换新 ,发布订阅
*超时释放:没有执行完的会有隐患(超时续约,看门狗机制)
*主从一致性问题(集群多个独立的redis节点)multiLock原理
redis分布式缓存
单节点存在的问题:
*数据丢失
*存储能力
*并发
*故障恢复
redis持久化
*rdb持久化(数据备份)
命令 save(会阻塞)-默认是服务停止的时候执行
命令bgsave,开启子线程(fork主线程得到子线程)(生成新的文件代替旧的)
配置文件定时(60秒)保存(触发bgsave),是否压缩(耗cpu,不建议启动)
恢复:开机读取
缺点:1rdb执行时间长,两次之间会有数据丢失风险,2压缩和写出rdb文件都比较耗时
*aof持久化(追加文件)
记录redis的操作日志,--命令日志文件
默认关闭,
开启方案:
1总是开启,先写到磁盘-效率低
2缓存区,先写道缓存,1秒后写磁盘 风险会丢失1秒数据(建议)
3系统写,让系统写到磁盘,风险高
恢复:开机执行
对比
rdb:整个快照 容易丢失数据,恢复快,压缩文件体积小,cpu高
aof:记录操作数据完整,恢复慢,cpu低。
redis主从架构
数据同步原理
主从第一步:全量同步,(主生成rdb发送)
redis哨兵(sentinel)架构
*监控(心跳机制)
(多数sentinel 认为下线就是下下线了)
*主从集群的自动故障恢复(自动将一个slave升级为master)
1首先判断slave断开节点长短
2判断slave优先级(配置文件)越小优先级越高 (0不选)
3判断offset,数据更新时间,时间越新优先级越高
4启动节点id,越小优先越高
*通知(充当redis客户端的作用,将故障信息发送到集群)
java用 配置redisTempalte配置哨兵地址
redis分片集群架构
作用
*海量数据存储
*高并发写的问题
特征
*多个master,每个数据不同
*每个master有多个slave
*master之间通过ping监控彼此健康状态
*客户端请求集群的任意节点,都会被转发到正确的节点(自动路由)
hash计算那个插槽(slot)是根据优先部分计算的(hash_tag)例如 {a}666,{a}777,根据a计算
java用 配置redisTempalte配置分片集群地址
redis的最佳实践
键值设计
优雅的设计key
*遵循基本格式:业务名称:数据名称:id(可读性 管理性)
*长度不超过44()
key是String,底层包含了 int,embstr,raw
embstr(连续,小于44字节,大了会升级为row),
row(不连续,查询会慢)
*不包含特色字符
value
拒绝bigKey(耗cpu 内存,阻塞)
*单个key的value不小于10KB
*对接集合:小于1000个
redis-cli-bigkeys找到他们
批量优化
单节点
mset(批量)插入- (M操作)
| 缺点:数据类型和key都要求一样,复杂类型不好处理
pipeline(管道)
*处理复杂类型的数据
*可以传各种命令
缺点(按照顺序执行 不具有原子性)(原子性:要么全部执行,要么全部不执行)
集群模式下
*必须将命令放到应该插槽(slot)中,否则失败,
解决方案:加一个相同的hash_tag 将key放同一个插槽(slot)
服务端优化
持久化
*缓存类型的不要持久化
*关rdb,建议用aof
*利用脚本在从节点做rdb 实现部分
慢查询
设置时间阈值-命令查出慢查询-优化
命令级安全优化
*设置密码
*禁止使用命令:()
config set (修改配置)
flushall(不可逆清空),flushdb(当前数据库)
keys
*不要使用默认端口
内存配置
数据内存
进程内存
缓存区内存
底层编码
String,底层包含了 int,embstr,raw
embstr(连续,小于44字节,大了会升级为row),
row(不连续,查询会慢)