Redis---五个基本数据结构与常用命令

Redis (Remote Dictionary Server )

NoSql–不仅仅是Sql

NoSql的四大分类
  1. KV键值对:
    • 新浪:redis
    • 美团:redis+Tair
    • 阿里,百度:redis+memecache
  2. 文档形数据库:
    • MongoDB
      • 是基于分布式文件存储的数据库,C++编写,主要用来处理大量的文档
      • MongDB是介于关系型数据库和非关系型数据库中间的产品
    • ConthDB
  3. 列存储数据库:
    • HBASE
    • 分布式文件数据库
  4. 图关系数据库
    • 不是存图形的,而是存关系的(如朋友圈社交网络)
    • Neo4j,InfoGrid;

Redis

redis能干嘛
  1. 内存存储,持久化,内存中是断电即失,所以需要持久化(rdb, aof)
  2. 效率高,可以用于高速缓存
  3. 发布订阅系统
  4. 地图信息分析
  5. 计时器,计数器(浏览量!)
特性
  1. 多样的数据类型
  2. 持久化
  3. 集群
  4. 事务

    中文官网
  • redis-benchmark 是一个压力测试工具
  • redis-cli 连接
  • redis-server +配置文件 按配置文件启动服务
基础知识
  • 默认有16个数据库 ,默认使用的是第0个数据库 可以使用
  • select [index] 切换数据库
  • DBSIZE 当前数据库大小
  • flushdb 清除当前数据库 FULSHALL 清空全部数据库
  • EXISTS [key] 判断当前key是否存在
  • move [key] 移除当前key
  • EXPIRE[key] 设置key的过期时间 (单位是秒) ttl [key] 查看当前key的剩余时间
  • redis是单线程的
  • 为什么redis的单线程的: 因为redis是基于内存操作的,CPU不是redis的性能瓶颈,redis的性能瓶颈是根据机器的内存和网络带宽。
  • redis为什么这么快:redis是将所有的数据全部放在内存中的,所以使用单线程去操作效率最高。多线程(CPU会发生上下文切换,耗时的操作),对于内存来说,如果没有上下文切换,效率就是最高的。
redis的数据类型
redis的key
五大基本数据类型
string
  • 操作和 java中的string有点像
  • append [key] 追加
  • incr [key] 值+1 decr [key] 值-1 经常用于做浏览量操作
  • incrby key 步长 值增加步长 decrby key 步长 值减少步长
  • 截取子串 getrange key index end 左闭右闭 end为-1 查看完整值
  • 替换子串 setrange key index newstr 从index开始,替换 newstr长度
  • setex [key] time 值 设值 加存活时间
  • setnx [key] 值 设值 ,如果值不存在则设值成功,如果值存在 则设值失败 (相当于不能修改)
  • mset k v k v … 批量设置 k v mget k k… 批量取值
  • msetnx k v k v 是原子性的操作 有一个设值失败则全部失败
    对象操作
    - set user:1{name:zz,age:3}
    - 巧妙的设计 : user:[id]:[filed]
    - mset user:1:name zhangsan user:1:age 3 mget user:1
    • getset k v 先返回原值 再设值
list
  • list可以玩成 栈,队列,阻塞队列
  • 所有的list的操作命令都是 l 开头的
  • lRang k begin end
  • lpush k v […] 头插队列 可以类似于 栈
  • Rpush k v […]
  • Lpop Rpop 左弹出 右弹出
  • lindex k index 通过下标获取值
  • llen k 获取 k的长度
  • lrem k num v 移除 list中的 num个v [从左往右移除]
  • ltrim k begin end 截取 begin-end的左闭右闭 且最终k保留的值是截取的内容
  • rpoplpush oldk newk 移除原列表的最右面元素 并将其左加到新列表中
  • lset index v 将列表中指定下标的值替换成新的值(相当于更新操作,如果指定下标没值则会报错)
  • linsert k BEFORE|AFTER v1 v2 在v1的前面|后面插入v2

list数据结构,实际上是一个链表,可以在左边或者右边插入数据
如果key不存在则创建链表,如果key存在,则新增内容。如果移除了所有值(空链表) 则不存在
可以用来做消息队列

set
  • set指定都是s开头的
  • sadd k v 添加元素
  • sMembers k 查看 k的所有值
  • sIsmember k 判断某一个值是不是在set集合中
  • sCard 获取set集合中的元素个数
  • sRem k v 删除 set中的指定元素
  • sRandmember k num 随机输出k的num个元素 (默认是1可以不写)
  • spop k 随机删除k的一个元素
  • smove k1 k2 v 将一个指定的值移动到另外一个集合中
    交并差集
  • sDiff k1 k2 k1 - k2 的差集
  • sInter k1 k2 k1和k2的交集 共同好友就是这样实现的
  • sUntion k1 k2 k1和 k2 的并集
hash
  • hset k mapk mapv [num 可以设置增量]
  • hget k
  • hmset k mk1 mv1 mk2 mv2 … set多个map
  • hmget k mk1 mk2… 获取多个字段值
  • hgetall k 获取全部的键跟值
  • hdel k mk 删除指定的map
  • hlen k 获取k中键值对的个数
  • hExists k mk 判断 hash中的指定字段是否存在
  • hkeys k 获取所有的key
  • hvals k 获取所有的值
  • hIncrby k mk num 增加num hDecrby k mk num 减少num
  • hsetnx k mk v 如果存在不可以设置 存在可以设置 (相当于更新)
    hash可以存储经常变更的数据,尤其是用户信息之类的
    hash更适合于对象的存储,String更加适合字符串的存储

hash的底层数据结构
压缩队列 or hashtable

当数据较少的时候使用 压缩队列
当数据量较大的时候使用 哈希表

Zset (sorted set有序集合)

在set的基础上增加了个值

  • zadd k score v … 可添加多个值,score表示排序的权重。
  • zRange k index end
  • zRevRange k index end 从大到小 进行排序 (反转)
  • zRangeByScore k minscore1 maxscore2 [withscores] 顺序输出 minScore1-maxScore 里的内容(加上withscores 则输出附带成绩)
  • -inf 表示负无穷 +inf表示正无穷
  • zRangeByScore
  • zrem k v 移除k中的v
  • zcard k 获取集合中的个数
  • zcount k score1 score2 获取指定区间的成员数量
    可以做b站排行榜应用

底层数据结构 : skiplist(跳表)增删改查的时间复杂度是 OlogN
在这里插入图片描述
为什么redis中 zset底层使用了 跳表,而不是b+Tree
数据库索引设计为B+Tree主要是解决I/O读取问题
因为B+树的原理是 叶子节点存储数据,非叶子节点存储索引,B+树的每个节点可以存储多个关键字,它将节点大小设置为磁盘页的大小,充分利用了磁盘预读的功能。每次读取磁盘页时就会读取一整个节点,每个叶子节点还有指向前后节点的指针,为的是最大限度的降低磁盘的IO;因为数据在内存中读取耗费的时间是从磁盘的IO读取的百万分之一
而Redis是 内存中读取数据,不涉及IO,因此使用了跳表
skiplist与平衡树、哈希表的比较

  • skiplist和各种平衡树(如AVL、红黑树等)的元素是有序排列的,而哈希表不是有序的。因此,在哈希表上只能做单个key的查找,不适宜做范围查找。所谓范围查找,指的是查找那些大小在指定的两个值之间的所有节点。
  • 在做范围查找的时候,平衡树比skiplist操作要复杂。在平衡树上,我们找到指定范围的小值之后,还需要以中序遍历的顺序继续寻找其它不超过大值的节点。如果不对平衡树进行一定的改造,这里的中序遍历并不容易实现。而在skiplist上进行范围查找就非常简单,只需要在找到小值之后,对第1层链表进行若干步的遍历就可以实现。
  • 平衡树的插入和删除操作可能引发子树的调整,逻辑复杂,而skiplist的插入和删除只需要修改相邻节点的指针,操作简单又快速。
  • 从内存占用上来说,skiplist比平衡树更灵活一些。一般来说,平衡树每个节点包含2个指针(分别指向左右子树),而skiplist每个节点包含的指针数目平均为1/(1-p),具体取决于参数p的大小。如果像Redis里的实现一样,取p=1/4,那么平均每个节点包含1.33个指针,比平衡树更有优势。
  • 查找单个key,skiplist和平衡树的时间复杂度都为O(log n),大体相当;而哈希表在保持较低的哈希值冲突概率的前提下,查找时间复杂度接近O(1),性能更高一些。所以我们平常使用的各种Map或dictionary结构,大都是基于哈希表实现的。
  • 从算法实现难度上来比较,skiplist比平衡树要简单得多。

redis zset为什么使用skiplist而不用平衡树

  1. 相对简单易于维护
  2. 内存消耗相对更低一点
  3. 链式结构,缓存局部性比平衡树要好很多
  4. 修改操作,跳表更简单
  • 排序后的集合通常是许多ZRANGE或ZREVRANGE操作的目标,即以链表的形式遍历跳跃表。使用这种操作,跳跃表的缓存局部性与其他类型的平衡树一样好。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值