目录
写在前面
大家好我是躺平哥,为了方便日后复习,我写下了这篇博客,里面并不涉及redis的安装,都是一些常见命令。
如果有写的不好的地方也请大家多多斧正,一起加油吧!
nosql有什么作用
nosql是为了解决性能问题,不需要进行io操作,数据直接存到内存中,那这么做得的好处是什么?——读的更快!
1缓解CPU压力
缓存数据库,完全在内存中,速度快数据结构简单
2缓解IO压力
nosql可以作为缓存数据库,一些频繁进行查询的数据放到缓存数据库中。
专门的数据用特定的方式存储,提高访问效率。
NoSQL数据库概述
NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL”, 泛指非关系型的数据库
NoSQL不依赖业务逻辑方式存储,而以简单的key-value模式存储。因此大大的增加了数据库的扩展能力。
- 不遵循SQL标准
- 不支持持ACID.但支持事务
- 远超于 SQL的性能
NoSQL适用场景。
●对数据高并发的读写。秒杀,高并发,海量数据
●海量数据的读写
●对数据高可扩 展性的。
NoSQL不适用场景
- 要事务支持
- 基于sql的结构化查询存储,处理复杂的关系需要即席查询
- (用不着sql的和用了sql也不行的情况.请考虑用NoSqI )
NoSQL优点
1.缓存数据库,完全在内存中,速度快,数据结构简单
2.减少io操作,数据库和表拆分,虽然破坏业务逻辑,即外加一个缓存数据库,提高数据库速度,也可以用专门的存储方式,以及针对不同的数据结构存储
数据库 | 功能 |
Memcache |
|
Redis |
|
MongoDB |
|
多路复用:
我的票还没有买到的时候我还能去干我其他的事情,让我的cpu一直在干活,不会停止。
开启本机redis
利用redis.conf开启:
启动redis命令:
redis基础认知
默认6379端口号
与memcache三点不同,支持多数据类型,持久化,单线程+多路io口复用
Reids数据类型
key值键位
key值的操作命令
key * 查看当前库所有的key
set key value 设置key值和value值
exists key 判断key是否存在
type key 查看key是什么类型
del key 删除指定的key数据
unlink key 根据value选择非阻塞删除
———仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作。告诉我们删除了,但是没有真正删除,后续会慢慢删掉。
expire key 10 10秒钟:为给定的key设置过期时间
ttl key 查看还有多少秒过期,-1表示永不过期(没设置过期时间),-2表示已过期
库的选择
- select 命令切换数据库
- dbsize 查看当前数据库的key数量
- flushdb 清空当前库
- flushall 通杀全部库
string字符串
基础知识
一个key对应一个value
string类型是二进制安全的,即可包含任何数据
value最多可以是512m
string常用命令
set key value 设置key值 。设置相同的key会覆盖掉
get key 查询key值
append key value 将给定的value追加到原值末尾
strlen key 获取值的长度
setnx key value 只有在key不存在的时候,设置key值
incr key 将key值存储的数字增1,只对数字值操作,如果为空,新增值为1
decr key 将key值存储的数字减1,只对数字值操作,如果为空,新增值为1
decr key 将key值存储的数字减1
incrby/decrby key 将key值存储的数字增减如步长,步长就是你每次加的值
补充:
原子操作
不会被打断,从开始到结束
单线程不会被打断
多线程很难说,被打断的就不是原子操作
补充额外的字符串参数:
mset key value key value..同时设置一个或者多个key-value
mget key key...同时获取一个或多个value
msetnx key value key value..同时设置一个或者多个key-value.当且仅当所有给定key都不存在
原子性,有一个失败则都失败
getrange key 获取key的起始位置和结束位置的值
setrange key value 将value的值覆盖起始位置开始
setex key <> value 设置键值的同时,设置过期时间
getset key value 用新值换旧值
String的数据结构
String的数据结构为简单动态字符串(Simple Dynamic String,缩写SDS)。是可以修改的字符串,内部结构实现上类似于Java的ArrayList,预分配冗余空间的方式来减少内存的频繁分配.。
如图中所示,内部为当前字符串实际分配的空间capacity 一般要高于实际字符串长度len。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间。需要注意的是字符串最大长度为512M。
Redis列表(List)
基础知识
单键多值.
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元索到列表的头部(边)或者尾部(边)。
它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
List常用命令:
lpush/rpush key value value...从左或者右插入一个或者多个值(头插就是lpush与尾插就是rpush)
lpop/rpop key 从左或者右吐出一个或者多个值(值在键在,值都没,键都没)。值被取出来之后,键就不存在了
rpoplpush key1 key2 从key1列表右边吐出一个值,插入到key2的左边
lrange key start stop 按照索引下标获取元素(从左到右)
lrange key 0 -1 获取所有值
lindex key index 按照索引下标获得元素
llen key 获取列表长度
linsert key before/after value newvalue 在value的前面插入一个新值
lrem key n value 从左边删除n个value值
lset key index value 在列表key中的下标index中修改值value
List的数据结构
List的数据结构为快速链表quickList.。
首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist ,也即是压缩列表。
但是链表不是连续的,他是需要两个额外的指针。
它将所有的元素紧挨着一起存储,分配的是一块连续的内存 。
当数据量此较多的时候才会改成quicklist。
因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next。
Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist 使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。。
总结:数据比较少的时候用ziplist即压缩列表,数据比较多的时候,使用多个ziplist组成的列表
集合set
基础知识
Redis set对外提供的功能与list 类似,是一个列表的功能。
特殊之处在于set可以自动排重的,当你要存储一个列表数据 ,不希望出现重复数据时, set是一个很好的选择,set提供了判断某个成员否在一个set集合内的重要接口,这个是list所不能提供的。
Redis的Set是string类型的无序集合。它底层其实是一个value为null的hash表。所以添加,删除,戟的复杂度都是0(1)。
set常用命令:
sadd key value value... 将一个或者多个member元素加入集合key中,已经存在的member元素被忽略
smembers key 取出该集合的所有值
sismember key value 判断该集合key是否含有改值 返回1 存在 0不存在
scard key 返回该集合的元素个数
srem key value value 删除集合中的某个元素
spop key 随机从集合中吐出一个元素
srandmember key n 随即从该集合中取出n个值,不会从集合中删除
smove value 将一个集合a的某个value移动到另一个集合b
sinter key1 key2 返回两个集合的交集元素,就是两个集合里的共有的元素
sunion key1 key2 返回两个集合的并集元素,就是两个集合里的所有元素
sdiff key1 key2 返回两个集合的差集元素(key1有的,key2没有)。前者有的,后者没有的
set的数据结构
Set数据结构是dict字典,字典是用哈希表实现的。
Java中HashSet的内部实现使用的是HashMap ,只不过所有的value都指向同一个对象。
Redis的set结构也是一样,它的内部也使用hash结构,所有的value都指向同一个内部值。
总结:内部利用哈希表进行位置的查找
Redis哈希(Hash)
基础知识
Redis hash是一个键值对集合。
Redis hash是一个string 类型的field和value的映射表, hash特别适合于存储对象。
类似Java里面的Map.
用户ID为查找的key ,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储。
hash的存储特点
failed和value映射表关系:通过他的field定位他的value
对象采用哪种存储结构好呢?
缺点:想修改其中一个属性的值不方便
例如想要修改他的age时要先变成一个对象进行修改,修改完之后还要变成json字符串。特别麻烦
好处:想改age直接取出来就可以改,不影响其他的字段
缺点:数据太分散了,例如太多user对象的时候user.id就太混乱了
优点:field value映射的形式:取值改值更加方便
hash常用命令
hset key field value 给key集合中的filed键添加并赋值value
hget key1 field 集合field取出value
hmset key1 field1 value1 field2 value2 批量设置hash的值
hexists key1 field 判断哈希表key中,给定域field是否存在
hkeys key 列出该hash集合的所有field
hvals key 列出该hash集合的所有value
hincrby key field increment 为哈希表key中的域field的值加上增量
hsetnx key field value 将哈希表key中的域field的值设置为value,当且仅当域field不存在
hash数据结构
Hash类型对应的数据结构是两种: ziplist (压缩列表),hashtable (哈希表)。当field-value长度较短且个数较少时,使用ziplist, 否则使用hashtable. 。
Redis有序集合Zset(sorted set)
基础知识
Redis有序集合zset 与普通集合set非常相似,是一个没有重复元素的字符串集合。
不同之处是有集合的每个成员都关联了一个评分(score) ,这个评分( score )被用来按照从最低分到最高分的方式排序其中的成员。集合成员是唯一的,但是评分可以是重复。
因为元素是有序的,所以你也可以很快的根据评分( score )或者次序( position )来获取一个范围的元素。
访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。
Zset常用命令
zadd key score1 value1 score2 value2 将一个或多个member元素及其score值加入到有序key中
zrange key start stop (withscores) 返回有序集key,下标在start与stop之间的元素,带withscores,可以让分数一起和值返回到结果集。
zrangebyscore key min max(withscores) 返回有序集key,所有score值介于min和max之间(包括等于min或max)的成员。有序集成员按score的值递增次序排列
zrevrangebyscore key max min (withscores) 同上,改为从大到小排列
zincrby key increment value 为元素的score加上增量
zrem key value 删除该集合下,指定值的元素
zcount key min max 统计该集合,分数区间内的元素个数
zrank key value 返回该值在集合中的排名,从0开始
第三位,从0开始
如何利用Zset实现一个文章访问量排行榜?
Zset数据结构
SortedSet (zset)是Redis提供的一个非常特别的数据结构, 一方面等价于Java的数据结构Map ,可以给每个元素value赋予一个权重 score ,另一方面它又类似于TreeSet ,内部的元素会按照权重score进行排序,可以得到每元素的名次,还可以通过score的范围来获取元素的列表。
zset底层使用了两个数据结构。
( 1 ) hash , hash的作用就关联元素value和权重score ,保障元素value的唯一性,可以通过元素value找到相应的score值。
(2 )跳跃表,跳跃表的目的在于给元素value排序,根据score的范围获取元素列表。
跳跃表(跳表)
1、简介:
有序集合在生活中比较常见,例如根据成绩对学生排名,根据得分对玩家排名等。对于有序集合的底层实现,可以用数组、平衡树、链表等。
数组不便玩素的插入、删除。
平衡树或红黑树虽然效率高但结构复杂。
链表查询需要遍历所有效率低。
Redis采用的是跳跃表。跳跃表效率堪比红黑树,实现远比红黑树简单。
2、实例:
对比有序链表和跳跃表,从链表中查询出51。
(1) 有序链表
要查找值为51的元素,需要从第一个元素开始依次查找、比较才能找到。共需要6次比较。
(2)跳跃链表
从第2层开始, 1节点比51节点小,向后比较。
21节点比51节点小,继续向后比较,后面就是NULL了,所以从21节点向下到第1层。
在第1层,41节点比51节点小,继续向后,61节点比51大,所以从41向下。
在第0层, 51节点要查找的节点,节点被找到,查找4次。