NoSsql not only sql 端口 6379 Http://redisdoc.com(命令集)
KV + Cache + Persistence
文档类数据库 MangDB
Redis (远程字典服务器)非关系型数据库
默认端口号 : 6379
基于内存的数据库,存储缓存用的数据。完成高并发,高速读写
Redis是一种key-value存储系统 value的值可以是多种数据结构类型
用作缓存数据理由:传统数据库,进行大量读取操作时效率很低。存储redis,就是将数据直接存储在内存上,提高开发效率。存储的数据为,数据量小,需要大量访问,而且主要进行读操作。(例如用户登陆的信息)
使用Redis的步骤:
- 添加redis依赖
- 配置redis连接池
- 导入RedisTemplate依赖 介入Spring帮助redis对java对象操作
1配置数据库连接池。(使用Spring配置JedisPoolConfig对象)
2为连接池配置工厂模型
3配置RedisTemplate(将java对象序列化后进行存储,将序列化取出反序列化Java对象)
(pojo类需要继承Serializable接口,完成序列化)
- 支持数据持久化
- 以多种数据类型存储
- 所有操作原子性,支持部分事务
Redis常用指令:
set : set k1 v1
get : get k1
select : Redis默认含有16个数据库,下标从0开始。使用 select ? 来切换数据库
DBsize: 显示当前数据库的key数量
FlushDB : 清除当前数据库所有key FlushALL 所有库清空
Key关键字:
kes * : 显示当前库所有key
exists key1 : key1 是否存在
move : move key1 2; 把key1移到3号库
ttl : ttl key1; 查看key1剩余时间 -1表示永不过期 -2已过期
expire : expire key1 10; 设置key1存活时间
type : 查看key1数据类型 type key1;
Redis支持五种数据类型 : String Hash List Set Zset(sorted set)
String:最基本数据类型,二进制安全(可以包含任何数据),最大存储512MB
常用指令: set/get/del/append/strlen
incre : 作用在数字,自增1 incre k1; incre k1 3 ; k1自增3
decre : 作用在数字,自减
getrange : 范围内截取字符串 getrange key1 0 3; key1字符串从0到3获取
setrange : 范围内设置 setrange key1 0 xxx; 将key1 的值从0设置值为xxx
setex(set with expire) : set的同时设置存活时间 setex key1 10 v1; 设置key1 v1 存货10秒
setnx(set if not exist) : setnx key1 v1; 如果key1不存在就设置进去,如果存在就不设置
mset : mset k1 v1 k2 v2 k3 v3;
mget : mget k1 k2 k3
指令:set key value // get key
append Incr(自增) IncrBy k2 3(k2增3) Decr decrby) getrange k1 0 -1(字符串指定区间取值) setRange k1 0 xxx(范围内赋值; mset k1 v1 k2 v2 k3 v3; mget k1 k2 k3; setnx(set not exit)
应用场景 :set get 简单k v操作
Hash: String类型以键值对的方式存储 类似Map(String,Object)
Hset : hset user id 101;
Hget :hget user id;
Hmset : hmset user1 id 101 name zhangsan age 18;
Hmget :hgetall user1;
hdel :hdel user name;
hkeys : hkeys user1;
hvals : hvals user1;
应用:存储,读取,修改用户属性,只修改某一个属性值
指令: HMset key k1 v1 k2 v2 // Hget key k1 Hget key k2
类似Map(String,Object) Hset/Hget/Hdel Hmset user name zhangsan id 11 age 20/Hmget user name /Hgetall user Hkeys/Hvals Hincrby user age 2(age增加2) Hsetnx user email xxx
应用场景:存结构化数据,例如object这种 key : id = 150 value: {name : zhangsan, age 18, sex 1}
List: String类型简单的双向链表 (一个key多个value) 列表。前后都可添加 列表为空列表消失
*Lpush: 从左往右插入 lpush key1 1 2 3 4 5
*Rpush: 从右往左插入
*LRange: 查看链表元素 LRange key1 0 -1; 查看链表key1 全部元素
LPop: 从左弹出
Rpop: 从右弹出
LRem : 删除链表中n个value Lrem k1 3 v; 删除k1中三个v
Ltrim :截取链表指定范围的值 再赋值给链表
应用:最新消息排行等功能(基于时间线),消息队列
指令:Lpush key “fuck” ; lrange key 0 10
Lpush/Rpush/Lrange lpop/rpop Lindex Llen Lrem list 5 value(删除n个value) Ltrim list 2 5(截取2-5部分重新赋值给list) RpopLpush list1 list2 Lset list index value; Linsert list index value;
应用场景: 某条博客评论列表, 利用 lrange实现简单分页,也可以实现简单的消息队列
Set: String类型无序无重复,底层由Hash表实现,为集合提供了交集,并集,差集等操作
应用:共同好友,好友推荐,(利用唯一性)统计网站的所有ip
Sadd: 添加
Smembers : 显示所有
Srandmember : 随机取出几个 Srandmember key1 3; 从k1中随机取出三个
Spop : 随机出栈
Sdiff: 差集
Sinter :交集
Sunion : 并集
指令:Sadd key1 value; Smembers key1;
Sadd/Smembers Sismember(是否存在某个元素) Scard(获取集合中元素个数) Srem set value(删除集合中元素) Srandmember set1 n(随机出n个数) Spop set1(随机出栈) Smove set1 set2 value(将set1中某个值付给set2) Sdiff set1 set2(差集) Sinter(交集) Sunion(并集)
应用场景: 去重, 交集 并集 差集 看看两个好友列表共同粉丝有哪些
Zset:String类型有序无重复集合 每个元素都关联一个double类型的分数score,根据score排序
Zadd :
Zrange :
Zrange with score
应用:排行榜,带权重的消息队列
指令: Zadd key score value; Zrange key 0 10
Zadd zset1 60 v1 90 v2 50 v3 80 v4 limit 2,2; Zrange zset1 0 -1; Zrevrange zset1 0 -1(逆序) Zrem zset1 v4(删除v4) Zcard Zcount zset1 60 80(统计60-80的个数)
Redis消息订阅发布
Subscribe订阅 c1 c2 c3
Publish推送 c1 helloworld
实现原理类似于"数组"+"链表"
“数组”是一个数据字典,保存了每一个频道,"链表"为订阅了这个频道的每个客户端
pub推送时,就将数据推送到相应的频道
sub订阅某个频道后,当有数据时推送过来消费
redis底层数据结构SDS
redis是用c语言写的,却并没有用c语言原生的字符串
原生字符串的缺点: 1. char数组,判断字符长度需要遍历数组找到第一个空,时间O(n) 2. append时需要可能需要重新扩容拷贝数组,3. 删除字符时可能造成内存泄漏 等空间浪费
SDS重要属性:
size: 当前数据占用大小
free: 当前数组剩余空闲大小
char[]: 字符数组
1. 保存了size值,O(1)复杂度判断字符串大小
2. 根据特定算法计算出可能会用到的free大小的空闲空间,尽量减少数据扩容,每次append只需要判断剩余空间是否小于当前空间, 决定是否需要扩容
3. 字符串缩短后,并不会立刻释放剩余空间,等经过几轮操作后还没有占用空闲空间,会释放掉,避免内存泄漏