Redis-简单介绍及基本数据类型【随笔一】
Redis 介绍及 NIO 原理介绍
磁盘的寻址速度是 ms 级的,内存的寻址速度是 ns 级的,内存寻址速度比磁盘快了 10w 倍。
成本问题:磁盘有磁道和扇区,一个扇区 512Byte,为了降低索引成本;4k 对齐,一般磁盘的默认格式化为 4k,操作系统无论你读多少,最少都是 4k;随着文件变大,访问速度变慢,硬盘 I/O 成为瓶颈;
数据库 4k 每页,索引 4k 每页
关系型数据库建表:必须给出 schema【类型:字节宽度】,存的时候更倾向于行级存储;内存里面准备了一个 b+ 树,b+ 树的叶子就是 4k 索引
读取数据 --> b+ 树叶子 --> 磁盘
单机部署
官网地址:https://redis.io/ 中文网地址:http://www.redis.cn/
下载地址:https://download.redis.io/releases/redis-6.2.6.tar.gz
yum install weget
cd /opt
mkdir soft
wget https://download.redis.io/releases/redis-6.2.6.tar.gz
tar xf redis-6.2.6.tar.gz
cd redis-src
make
...yum install gcc
... make distclean
make
make install PREFIX = /opt/middleware/redis6
vi /etc/profile
...export REDIS_HOME=/opt/middleware/redis6
...export PATH=$PATH:$REDIS_HOME/bin
source /etc/porfie
cd utils
./install_service.sh 【安装服务实例】
service redis_6379 start/stop/stauts 【服务实例 启动/关闭/运行状态 命令】
cd /etc/init.d/ 【查询实例脚本】$ find . -type f -executable
./redis-benchmark //用于进行redis性能测试的工具
./redis-check-dump //用于修复出问题的dump.rdb文件
./redis-cli //redis的客户端
./redis-server //redis的服务端
./redis-check-aof //用于修复出问题的AOF文件
./redis-sentinel //用于集群管理//这样来启动redis客户端了
$ ./redis-cli
//用set指令来设置key、value
127.0.0.1:6379> set name "roc"
OK
//来获取name的值
127.0.0.1:6379> get name
"roc"
//通过客户端来关闭redis服务端
127.0.0.1:6379> shutdown
127.0.0.1:6379>
NIO 原理介绍
NIO:每次请求启动一个线程来处理,当多个请求并发访问时,需要启动多个线程。socket 在这个时期是blocking 的。
NIO:内核中的socket 可以是 nonblock 的,一个线程死循环遍历文件描述符;轮询发生在用户空间,同步非阻塞;问题:若有1000fd代表用户需要轮询调用1000次kernel【成本问题,内核态->用户态切换】
NIO:轮询发生在用户空间,内核一次性 select 1000fd,返回准备好了的 fd,减少【用户态->内核态】的切换。多路复用
NIO:为避免fd数据在内核和用户间拷来拷去,引入共享空间【mmap】,用户态和内核态共享这个空间;用户空间只需要将1000fd写入共享空间的红黑树,内核拿到fd,判断是否准备好数据,准备好则将其放到链表中,用户则只需要读取链表准备好的数据。
Redis 介绍
Redis 是一个开源(BSD 许可)的内存数据结构存储系统,用作数据库、缓存和消息代理。Redis 提供数据结构,例如字符串、哈希、列表、集合、具有范围查询的排序集合、位图、超日志、地理空间索引和流。Redis 具有内置复制、Lua 脚本、LRU 驱逐、事务和不同级别的磁盘持久性,并通过 Redis Sentinel 和 Redis Cluster 自动分区提供高可用性。
与传统关系型数据库不同的是 Redis 的数据是存在内存中的,所以读写速度非常快,因此 redis 被广泛应用于缓存方向,每秒可以处理超过 10万次读写操作,是已知性能最快的 Key-Value DB。另外,Redis 也经常用来做分布式锁。除此之外,Redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。
Redis的优点和缺点
优点:
- 读写性能优异, Redis读取速度高达110000次/s,写的速度也达到了81000次/s。
- 数据结构丰富,有五种数据类型的value,分别是 String、Hash、List、Set、ZSet。
- 支持数据持久化,有AOP和RDB两种持久化方式。
- 支持事务,Redis是单进程单线程的,其所有操作都是原子性的,同时Redis还支持对几个命令合并后的原子性操作;但是与传统数据库事务不同的是,其不支持回滚操作。
- 支持主从复制,主机会自动将数据同步到从机,可以支持读写分离。
- 可以通过 Redis Sentinel 和 Redis Cluster 自动分区提供高可用。
缺点:
Redis是内存数据库,数据库容量受物理内存限制,不能用作海量数据的高性能读写,虽然redis本身有key过期策略,但是还是需要提前预估和节约内存。如果内存增长过快,需要定期删除数据。
如果进行完整重同步,由于需要生成rdb文件,并进行传输,会占用主机的CPU,并会消耗现网的带宽。不过redis2.8版本,已经有部分重同步的功能,但是还是有可能有完整重同步的。比如,新上线的备机。
修改配置文件,进行重启,将硬盘中的数据加载进内存,时间比较久。在这个过程中,redis不能
提供服务。
Redis为什么这么快
完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1)
数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的
采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗
使用多路 I/O 复用模型,非阻塞 IO
使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求
基本数据类型
redis提供了五种基本数据类型:字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)。
数据类型 | 简介 | 应用场景 |
---|---|---|
String | 字符串,数值,bitmap,二进制安全 | 秒杀、活跃用户统计、点赞数、评论数 |
Hash | 键值对的散列表 | 详情页 |
List | 链表(双向链表) | 消息队列 |
Set | 哈希表实现,元素不重复 | 共同好友,抽奖 |
Sorted Set | 有序集合,跳跃表 | 排行榜,带权重的消息队列 |
正反向索引:正向索引 0-(len-1) ,反向索引 -1~(-len)
二进制安全:redis存储的是字节
时间单位:
EX
seconds – 设置指定的过期时间,以秒为单位。
PX
毫秒——设置指定的过期时间,以毫秒为单位。
EXAT
timestamp-seconds – 设置密钥过期的指定 Unix 时间,以秒为单位。
PXAT
timestamp-milliseconds – 设置密钥过期的指定 Unix 时间,以毫秒为单位。PERSIST – 删除与密钥关联的生存时间。
Redis 的 String 类型 和 bitmap
官网命令:https://redis.io/commands#string
String 不仅可以面向
字符串
操作,还可以面向数值
操作和bitmap
操作。
redis-cli -p 6379
select 0
set k1 hello
help @string
keys *
FLUSHDB
一、面向String操作
命令 | 描述 |
---|---|
APPEND key value
|
追加一个value到key上 |
GET key
|
返回key的value |
GETDEL key
|
获取key的value,并删除 |
GETEX key[EX seconds …]
|
获取key的值,并可选择设置其过期时间 |
GETRANGE key start end
|
获取存储在key上的value的一个子字符串 |
GETSET key
|
设置一个key的value值,并获取设置前的值 |
LCS key1 key2
|
获取多个key的value中都同时存在的字符并返回 |
MGET key [key…]
|
批量获取key 对应的value值 |
MSET key [key value…]
|
批量设置 key-value 键值对 |
MSETNX key value [key value…]
|
批量设置 key-value 键值对【若key不存在】 |
PSETEX key milliseconds value
|
与SETEX 完全相同,唯一的区别是过期时间以毫秒单位
|
SET key value [EX seconds …]
|
设置一个key的value值,并可选择设置其过期时间 |
SETEX key seconds value
|
设置key-value并设置过期时间(单位:秒) |
SETNX key value
|
当key不存在时,设置key的value值 |
SETRANGE key offset value
|
覆盖指定key部分value,从指定的偏移量开始,覆盖value的整个长度 |
STRLEN key
|
获取指定key的值的长度 |
SUBSTR key start end
|
获取存储在key上的value的一个子字符串 |
set k1 ssss nx k1不存在则设置k1的值为ssss
set k2 ssss xx k2存在则更新k2的值为ssss
mset k1 ssss k2 dddd 设置k1的值为ssss、k2的值为dddd
mget k1 k2 获取k1、k2的值
append k1 work 在k1的值后面追加work
GETRANGE K1 0 5 获取k1 索引0-5的值
GETRANGE K1 0 -1 获取k1 索引0到-1的值【即所有】
SETRANGE K1 6 SSDDDDS 设置K1 从索引6开始后续的值
STRLEN K1 获取k1值的长度GETSET K1 121 设置k1为121并且返回设置前的k1的值
MSETNX k1 123 k2 456 批量设置k的值
二、面向数值操作
命令 | 描述 |
---|---|
INCR key
|
执行原子加1操作 |
INCRBY key increment
|
原子增加一个整数 |
INCRBYFLOAT key increment
|
原子增加一个浮点数 |
DECR key
|
整数原子减1 |
DECRBY key decrement
|
原子减少指定的整数 |
TYPE K1 【描述的是value的类型】
OBJECT encoding k1SET K1 99
TYPE K1
INCR K1
TYPE K1
DECR K1
INCRBY K1 11
DECRBY K1 12
INCRBYFLOAT K1 0.5
使用案例:秒杀,抢购,详情页,点赞数,评论数,关注数;规避并发下对数据库的事务操作,完全由redis内存操作代替
三、面向bitmap操作
命令 | 描述 |
---|---|
BITCOUNT key [start end [BYTE|BIT]]
|
统计字符串被设置为1的bit数 |
BITFIELD key [Get encoding offset]…
|
对字符串执行任意位域整数运算 |
BITFIELD_RD key GET encoding offset
|
对字符串执行任意位域整数运算。BITFIELD 的只读变体 |
BITPOS key bit [start…]
|
返回字符串里面第一个被设置为1或者0的bit位 |
GETBIT key offset
|
返回存储在 key 的字符串值中偏移处的位值 |
SETBIT key offset value
|
设置或清除存储在 key 的字符串值的偏移量位 |
BITOP operation destkey key [key…]
|
在字符串之间执行按位运算 |
SETBIT k1 1 1 设置k1的索引为1的bit的二进制位为1
SETBIT K1 7 1
GETBIT k1 7BITPOS k1 1 0 0 查找k1的值中索引0~0之间的字节中二进制位为1的第一个二进制位的索引【字符串中的字符索引】
BITCOUNT K1 0 0 字符串索引【0-0】之间的字符中二进制位1出现的次数# 位运算
FLUSHDB
SET k1 A
SET K2 B
BITOP AND andkey k1 k2
get andkey => @
BITOP OR orkey k1 k2
get orkey => C
使用案例:
一、统计用户的登录天数,且查询日期随机
用户ID做key,一年中的第几天为 二进制位索引 登录时,其位置的值置为1
SETBIT ak 1 1 SETBIT ak 365 1 BITCOUNT ak 0 -1 ===> 2 # 一年登录了两次 STRLEN ak # 查看一年占用的字符总数为【46】,占用空间小
二、某商城618活动:送礼物,需要备货多少礼物;存在2e用户;活跃用户统计
# 时间作为key 用户ID映射到二进制位 # 如下,用户1 2022-01-01 登录,用户6 2022-01-02 登录 SETBIT 20220101 1 1 SETBIT 20220102 6 1BITOP OR activeKey 20220101 20220102 BITCOUNT activeKey 0 -1
Redis 的 List 类型
官网命令:https://redis.io/commands#list
同向命令:栈,反向命令:队列,数组,阻塞、单播队列FIFO
命令 | 描述 |
---|---|
LPUSH RPUSH
|
从队列左边/右边入队一个或多个元素 |
LPUSHX RPUSHX
|
当队列存在时,从队列左边/右边入队一个或多个元素 |
LPOP RPOP
|
从队列左边/右边出队一个元素 |
LINDEX
|
通过索引获取一个元素【索引从0开始】 |
LINSERT
|
在列表中的一个元素【值】之前/之后插入一个元素 |
LLEN
|
获取列表的长度 |
LMOVE
|
从列表中弹出一个元素,将其推送到另一个列表并返回 |
LMPOP
|
从提供的key列表中的第一个非空列表中弹出指定个数的元素,返回元素个数受列表限制,最多为列表所有元素。 |
LPOS
|
返回元素在列表中出现的索引位置【可以存在多个】 |
LRANGE
|
从列表获取指定索引范围内的元素 |
LREM
|
移除列表中指定个数的元素【正数:左到右,负数:右到左,0:所有】 |
LSET
|
设置队列里面一个元素的值 |
RPOPLPUSH
|
原子删除列表的最后一个元素(尾部),并将该元素推到目标列表的第一个元素(头部)处 |
LTRIM
|
修剪现有列表,使其仅包含指定范围内的元素 |
BLPOP BRPOP
|
从第一个非空列表的左边/右边弹出一个元素,若所有列表都不存在元素,则阻塞等待直到有元素可以弹出【可以设置超时时间】 |
BLMOVE
|
从列表中弹出一个元素,将其推送到另一个列表并返回,若不存在元素则阻塞等待【可以设置超时时间】 |
BLMPOP
|
从提供的key列表中的第一个非空列表中弹出指定个数的元素,返回元素个数受列表限制,最多为列表所有元素;若不存在元素,则阻塞等待【可以设置超时时间】 |
BRPOPLPUSH
|
该命令与RPOPLPUSH 行为一样,只是当列表不存在元素时,会阻塞等待【可以设置超时时间】
|
简单使用
LPUSH K1 a b c d e f => f e d c b a
RPUSH K2 a b c d e f => a b c d e fLPOP K1 => f
RPOP K2 => fRPOP K1 => a
LPOP K2 => a
同向命令: 栈,反向命令:队列LRANGE k1 0 -1 => e d c b
LRANGE K2 0 -1 => b c d eLINDEX K1 2 => c
LSET K1 2 3333 => e d 3333 bLPUSH k1 2 2 2
RPUSH k1 2 2 => 2 2 2 e d 3333 b 2 2
LREM K1 2 2 => 2:正数,移除左边开始两个2 => 2 e d 3333 b 2 2LPUSH k3 1 2 3 4 5 6 => 6 5 4 3 2 1
LINSERT K3 after 6 a => 从左边开始在第一个元素6后面插入一个a => 6 a 5 4 3 2 1
LINSERT K3 before 3 a => 从左边开始第一个元素3前面插入一个a => 6 a 5 4 a 3 2 1LLEN K3 => 8
LTRIM K3 2 5 ==> 移除K3 索引2~5[不包含]两端的元素 =》 5 4 a 3
Redis 的 Hash 类型
官网命令:https://redis.io/commands#hash
命令 | 描述 |
---|---|
HSET
|
设置hash里面一个字段的值 |
HMSET
|
设置hash多个字段的值 |
HGET
|
获取hash中指定字段的值 |
HMGET
|
获取hash中多个字段的值 |
HKEYS
|
获取hash的所有字段 |
HVALS
|
获取hash的所有值 |
HGETALL
|
获取hash中全部的字段的键值对 |
HINCRBY
|
将hash中指定字段的值增加给定的数值 |
HINCRBYFLOAT
|
将hsah中指定字段的值增加给定的浮点数 |
HDEL
|
删除一个或多个hash的字段 |
HEXISTS
|
判断字段是否存在于hash中 |
HLEN
|
获取hash中所有字段的数量 |
HRANDFIELD
|
随机从hash中获取指定个数的字段【最多为所有的字段】 |
HSCAN
|
迭代hash里面的元素 |
HSETNX
|
当字段不存在时,设置这个字段的值 |
HSTRLEN
|
获取hash里面指定字段的长度 |
简单使用
HSET akieay name akieay
HMSET akieay age 22 sex 2 address 0151
HGET akieay name => akieay
HMGET akieay name age sex => akieay 22 2HKEYS akieay => name age sex address
HVALS akieay => akieay 22 2 0151
HGETALL akieay => name:akieay age:22 sex:2 address:0151HINCRBY akieay age 3 => age:25
HINCRBYFLOAT akieay age 0.5 => age:25.5HDEL akieay address
HGETALL akieay => name:akieay age:22 sex:2HEXISTS akieay name => 1
HEXISTS akieay address => 0HLEN akieay => 3
HRANDFIELD akieay 2 => name sexHSETNX akieay address 1065
HGETALL akieay => name:akieay age:22 sex:2 address:1065HSTRLEN akieay name => 6HSCAN akieay 2
场景:点赞,收藏,详情页
Redis 的 Set 类型
无序、去重
官网命令:https://redis.io/commands#set
命令 | 描述 |
---|---|
SADD
|
添加一个多多个元素到Set集合里 |
SREM
|
从集合里面删除一个或多个元素 |
SPOP
|
从集合中移除并返回一个或多个随机成员] |
SCARD
|
获取集合里面的元素数量 |
SISMEMBER
|
确定一个给定的成员是否是集合的成员,1:是,0:不是 |
SMISMEMBER
|
返回每个成员是否为存储到key中的集合成员,1:是,0:不是 |
SMEMBERS
|
返回集合中的所有成员 |
SRANDMEMBER
|
从集合中随机获取指定个数的元素(默认1);当数值为正数时,不重复,不一定满足个数;当数值为负数时,可重复,一定满足个数 |
SSCAN
|
迭代集合里面的元素 |
SINTER SINTERSTORE
|
获取多个集合的交集,【SINTERSTORE 会将结果存储到指定的结果集中】
|
SUNION SUNIONSTORE
|
获取多个集合的并集,【SUNIONSTORE 会将结果存储到指定的结果集中】
|
SDIFF SDIFFSTORE
|
获取多个集合的差集,【SDIFFSTORE 会将结果存储到指定的结果集中】
|
SINTERCARD
|
这个命令类似于SINTER,但是它不返回结果集,而是返回结果的基数 |
SMOVE
|
移动集合里面的一个元素到另一个集合中 |
简单使用
SADD k1 1 2 3 4 5 6
SMEMBERS k1 => 1 2 3 4 5 6
SREM k1 4 5 6
SMEMBERS k1 => 1 2 3
SPOP k1 2
SMEMBERS K1 => 2
SCARD k1 => 1SISMEMBER k1 2 => 1
SISMEMBER k1 1 => 0
SMISMEMBER k1 1 2 3 => 0 1 0
SADD k1 1 2 3
# 正数,不重复,不一定满足个数;负数,可重复,一定满足个数;0,不返回
SRANDMEMBER k1 4 => 1 2 3
SRANDMEMBER k1 -4 => 2 1 3 3SADD k2 1 2 3 4 5
SADD k3 4 5 6 7 8
SINTER k2 k3 => 交集:4 5
SINTERSTORE inkey K2 K3
SMEMBERS inkey => 4 5SUNION K2 K3 => 并集:1 2 3 4 5 6 7 8SDIFF K2 K3 => 取k2相对于k3的差集:1 2 3
SDIFF K3 K2 => 取k3相对于k2的差集:6 7 8SMOVE k2 k3 1
SMEMBERS k2 => 2 3 4 5
SMEMBERS k2 => 1 4 5 6 7 8
应用场景:抽奖
用户 <10 或 用户 > 10
很多粉丝,三个礼物,每个人只有一件:k1存人,SRANDMEMBER K1 3
很多粉丝,三个礼物,每个人可以多件:k1存人,SRANDMEMBER K1 -3
很多礼物,20个礼物,3个人,可以多件:k1存礼物,SRANDMEMBER K1 3公司年会:一次抽一件礼物
SPOP K1 弹出一个
Redis 的 Sorted Set 类型
排序:分值,名称字典序
官网命令:https://redis.io/commands#sorted-set
命令 | 描述 |
---|---|
ZADD
|
添加一个或多个成员到集合【重复的成员会更新分数】 |
ZRANGE
|
返回集合中指定范围内的成员 |
ZREVRANGE
|
从最高到最低排序,返回集合中指定范围内元素 |
ZRANK
|
返回集合成员在集合中的排名 |
ZREVRANK
|
除了颠倒了顺序外,其行为与 ZRANK 基本一致
|
ZSCORE
|
返回集合成员分数 |
ZMSCORE
|
返回集合中指定成员的分数 |
ZINCRBY
|
为指定成员增加指定的分数 |
ZCARD
|
获取集合中的成员数量 |
ZCOUNT
|
返回分数范围内的成员数量 |
ZREM
|
移除集合中的指定成员 |
ZSCAN
|
迭代集合里面的元素 |
ZREMRANGEBYSCORE
|
删除集合中分数介于min和max之间的元素 |
ZREMRANGEBYRANK
|
根据rank移除处于start到stop之间的排名的元素,正数表示正序排名,0表示分数最低的,负数表示倒叙排名 |
ZPOPMIN
|
移除并返回集合中已排序的最低分的成员 |
ZPOPMAX
|
移除并返回集合中已排序的最高分的成员 |
ZRANDMEMBER
|
从集合中随机获取指定个数的元素(默认1);当数值为正数时,不重复,不一定满足个数;当数值为负数时,可重复,一定满足个数 |
ZRANGESTORE
|
返回集合中指定排名范围内的成员,并将结果存储到指定key中 |
ZRANGEBYSCORE
|
返回已排序集合中分数介于min和max之间的元素,并且按分数从低到高排序【包含min和max】 |
ZREVRANGEBYSCORE
|
除了颠倒了顺序外,其行为与 ZRANGEBYSCORE 基本一致
|
ZLEXCOUNT
|
当以相同的分数插入已排序集合中的所有元素时,为了强制按字典顺序排序,该命令返回已排序集合中的元素数量,其值介于min和max之间 |
ZRANGEBYLEX
|
当以相同的分数插入已排序集合中的所有元素时,为了强制按字典顺序排序,该命令返回已排序集合中的元素,其值介于min和max之间 |
ZREVRANGEBYLEX
|
除了颠倒了顺序外,其行为与 ZRANGEBYLEX 基本一致
|
ZINTER
|
取多个集合的交集,并将结果返回给客户端 |
ZINTERCARD
|
取多个集合的交集,并将结果集的基数返回给客户端 |
ZINTERSTORE
|
取多个集合的交集,并将结果存储在指定的key中 |
ZUNION
|
取多个集合的并集,并将结果返回给客户端 |
ZUNIONSTORE
|
取多个集合的并集,并将结果存储在指定的key中 |
ZDIFF
|
取多个集合的差集,并将结果返回给客户端 |
ZDIFFSTORE
|
取多个集合的差集,并将结果存储在指定的key中 |
ZMPOP
|
从提供的集合中的第一个非空集合中弹出一个或多个成员-分数对元素。 |
ZREMRANGEBYLEX
|
当以相同的分数插入已排序集合中的所有元素时,为了强制按字典顺序排序,该命令删除集合中min到max位置的所有元素 |
BZMPOP
|
ZMPOP 的阻塞体,行为与 ZMPOP 基本一致,没有元素时会阻塞等待
|
BZPOPMAX
|
ZPOPMAX 的阻塞体,行为与 ZPOPMAX 基本一致,没有元素时会阻塞等待
|
BZPOPMIN
|
ZPOPMIN 的阻塞体,行为与 ZPOPMIN 基本一致,没有元素时会阻塞等待
|
简单使用
ZADD k1 8 apple 2 banana 3 organge => 添加元素 前面为分数,后面为元素值
ZRANGE k1 0 -1 => 元素按分数从小到大排序:banana organge apple
ZREVRANGE k1 0 -1 => 元素按分数从大到小排序:apple organge banana
ZRANK k1 banana => 获取元素 "banana"【从小到大】的排名:0 【排名索引从0开始】
ZREVRANK k1 banana => 获取元素 "banana"【从大到小】的排名:2ZSCORE k1 apple => 获取元素 "apple" 的分值:8
ZMSCORE k1 apple banana organge => 获取多个元素的分值:8 2 3
ZCARD k1 => 获取集合中成员的数量:3
ZCOUNT k1 0 5 => 获取集合中分数[0-5]之间的元素数量:2ZREM k1 apple => 删除元素 "apple"
ZRANGE k1 0 -1 => banana organge
ZINCRBY k1 2 banana => 元素 "banana" 分值增加2
ZSCORE k1 banana => 4ZADD k1 8 apple 2 banana 3 organge
ZREMRANGEBYSCORE k1 0 5 => 删除分数在[0-5]之间的元素
ZRANGE k1 0 -1 => appleZADD k1 8 apple 2 banana 3 organge
ZREMRANGEBYRANK k1 2 3 => 删除排名在[2-3]之间的元素,排名从0开始
ZRANGE k1 0 -1 => banana organgeZADD k1 8 apple 2 banana 3 organge
ZPOPMIN k1 2 => 根据排名从小到大弹出2个元素
ZRANGE k1 0 -1 => appleZADD k1 8 apple 2 banana 3 organge
ZPOPMAX k1 2 => 根据排名从大到小弹出2个元素
ZRANGE k1 0 -1 => bananaZADD k1 8 apple 2 banana 3 organge
# 从集合中随机获取指定个数的元素(默认1);当数值为正数时,不重复,不一定满足个数;当数值为负数时,可重复,一定满足个数
ZRANDMEMBER k1 4 => apple organge banana
ZRANDMEMBER k1 -4 => banana apple organge banana
# 返回集合中指定排名【从小到大】范围内的成员,并将结果存储到指定key中【排名从0开始】
ZRANGESTORE newkey k1 0 1
ZRANGE newkey 0 -1 => banana organge
ZRANGEBYSCORE k1 0 5 => 获取分数为[0-5]之间的元素并从小到大排列:banana organge
ZREVRANGEBYSCORE k1 5 0 => 获取分数为[5-0]之间的元素并从大到小排列:organge bananaZADD k2 0 a 0 b 0 c 0 d 0 e
ZLEXCOUNT k2 - + => 5 【可以使用 - 和 + 表示得分最小值和最大值】
ZLEXCOUNT k2 [b [f => 4
ZRANGEBYLEX - + => a b c d e
ZRANGEBYLEX k2 [b [e => b c d e
ZREVRANGEBYLEX k2 [e [b => e d c b
ZREMRANGEBYLEX k2 [b [e => a# 集合操作 交、并、差集
FLUSHDB
ZADD k1 80 tom 70 jk 60 kk 30 cc
ZADD k2 60 tom 94 jk 40 kk 20 tt
# 交集
ZINTER 2 k1 k2 withscores => kk:100 tom:140 jk:164
ZINTERSTORE inkey 2 k1 k2 => 取k1与k2的交集,并将结果存入inkey
ZRANGE inkey 0 -1 withscores => kk:100 tom:140 jk:164# 并集
ZUNION 2 k1 k2 withscores => tt:20 cc:30 kk:100 tom:140 jk:164
# 取k1与k2的并集,并根据权重合并分数,然后添加到unkey中,分数计算如下:
# k1中tt分数不存在,k2中tt分数为20,而k1与k2权重比为1:0.5,所以合并后tt分数为10
# 同理,k1 jk:70,k2 jk:94,k1:k2 = 1:0.5,分数合并k1-jk:70,k2-jk:47,合并后jk:117
ZUNIONSTORE unkey 2 k1 k2 weights 1 0.5
ZRANGE unkey 0 -1 withscores => tt:10 cc:30 kk:80 tom:110 jk:117
# 取k1与k2的并集,并根据权重合并分数【合并方式为取最大值】,然后添加到unkey中,分数计算如下:
# k1 tt不存在,k2 tt:20,k1:k2 = 1:0.5,分数合并k1-tt不存在,k2-tt:10,合并取最大值tt:10
# k1 jk:70,k2 jk:94,k1:k2 = 1:0.5,分数合并k1-jk:70,k2-jk:47,合并取最大值jk:70
ZUNIONSTORE unk2 2 k1 k2 weights 1 0.5 aggregate MAX
ZRANGE unk2 0 -1 withscores => tt:10 cc:30 kk:60 jk:70 tom:80# 差集
ZDIFF 2 k1 k2 withscores => 取k1与k2的差集,以k1数据为主:cc:30
ZDIFF 2 k2 k1 withscores => 取k2与k1的差集,以k2为主:tt:20
应用:
ZRANGE k1 0 -1 withsocres => 会根据分值的改变而改变元素的位置 歌曲热度排行
跳跃表
普通链表
跳跃表
跳跃列表是一种高效的动态数据结构,它是基于链表实现的。它允许快速查询一个有序连续元素的数据链表,而其快速查询是通过维护一个多层次的链表来实现的,且每一层链表中的元素是前一层链表元素的子集。
一开始时,算法在最稀疏的层次进行搜索,直至需要查找的元素在该层两个相邻的元素中间。这时,算法将跳转到下一个层次,重复刚才的搜索,直到找到需要查找的元素为止。
可以看到,这里一共有3层,最上面就是最高层 L3,最下面的层就是最底层 L1,然后每一列中的链表节点中的值都是相同的,用指针来连接着。跳跃表的层数跟结构中最高节点的高度相同。理想情况下,跳跃表结构中第一层中存在所有的节点,第二层只有一半的节点,而且是均匀间隔,第三层则存在1/4的节点,并且是均匀间隔的,以此类推,这样理想的层数就是 logN。
跳跃表的特性:
- 跳表是基于链表建立多级索引的动态数据结构,每一层都是一个有序的链表;
- 每一层都是一个有序的链表,排列顺序为由高层到底层,都至少包含两个链表节点,分别是前面的head节点和后面的nil节点;
- 最底层的链表包含了所有的元素;
- 如果一个元素出现在某一层的链表中,那么在该层之下的链表也全都会出现(上一层的元素是当前层的元素的子集);
- 链表中的每个节点都包含两个指针,一个指向同一层的下一个链表节点,另一个指向下一层的同一个链表节点;
- 跳表的查询时间复杂度是 O*(log(*n)),而单链表的查询时间复杂度是 O(n)
- 跳表需要额外的内存空间存储索引,实现空间换时间
- 动态插入,删除数据时,跳表需要维护索引大小平衡性,避免退化为单链表
Redis-简单介绍及基本数据类型【随笔一】相关推荐
- redis字符串匹配_Redis的数据类型和抽象概念介绍
Redis 不是一个 简单的 key-value 存储,实际上它是一个数据结构服务器,它支持不同类型的值.也就是说,在传统的key-value存储中,你将一个字符串的key关联到一个字符串的值上:而在 ...
- Redis 学习笔记-NoSQL数据库 常用五大数据类型 Redis配置文件介绍 Redis的发布和订阅 Redis_事务_锁机制_秒杀 Redis应用问题解决 分布式锁
1.NoSQL数据库 1.1 NoSQL数据库概述 NoSQL(NosQL = Not Only sQL ),意即"不仅仅是sQL",泛指非关系型的数据库.NoSQL不依赖业务逻辑 ...
- Redis数据库特点的简单介绍
首先介绍一下Redis,Redis是一个高性能的Key-value数据库,它属于NoSQL数据库. 关于NoSQL数据库我们在这里也做一下简单的介绍,数据库分为关系型数据库比如MySQL和非关系型数据 ...
- 简单介绍Python中的几种数据类型
大体上把Python中的数据类型分为如下几类: Number(数字) 包括int,long,float,complex String(字符串) 例如:hello,"hello",h ...
- 【修真院JAVA小课堂】redis缓存集群简单介绍
大家好,我是IT修真院郑州分院第11期的JAVA学员,一枚正直纯洁善良的java程序员. 今天给大家分享一下,redis缓存集群简单介绍. 1.背景介绍 redis是一个key-value存储系统.和 ...
- 简述python中的几种数据类型,简单介绍Python中的几种数据类型
简单介绍Python中的几种数据类型 python 里面分为 基本数据类型 和 复合数据类型 基本数据类型包括:数值 字符串 布尔 和 none 复合数据类型包括:列表 元组 字典 和集合怎么算是深情 ...
- 三大缓存框架ehcache、memcache和redis的介绍
三大缓存框架ehcache.memcache和redis的介绍 2016-04-12 架构说 4964 阅读 最近项目组有用到这三个缓存,去各自的官方看了下,觉得还真的各有千秋!今天特意归纳下各个缓存 ...
- NoSQL数据库之Redis数据库:Redis的介绍与安装部署(redis-2.8.19/3.2.5)
NoSQL(NoSQL = Not Only SQL),它指的是非关系型的数据库.随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的w ...
- Redis系统性介绍
虽然Redis已经很火了,相信还是有很多同学对Redis只是有所听闻或者了解并不全面,下面是一个比较系统的Redis介绍,对Redis的特性及各种数据类型及操作进行了介绍.是一个很不错的Redis入门 ...
- redis学习(二) redis数据结构介绍以及常用命令
redis数据结构介绍 我们已经知道redis是一个基于key-value数据存储的数据结构数据库,这里的key指的是string类型,而对应的value则可以是多样的数据结构.其中包括下面五种类型: ...
最新文章
- Go 学习笔记(63)— Go 中的 for ... range 对切片和数组的差异
- 化繁为简,一张图看懂梯度、散度、旋度、Jacobian、Hessian和Laplacian
- 全球75亿美元的网络安全险 会是保险业下一块金矿吗?
- python找不到os模块_python之os模块
- linux 内核主线,为AM335x移植Linux内核主线代码(41)Ethernet结论篇
- CodeForces - 888C K-Dominant Character 思维
- 网络流专题(完结撒花)
- JQuery实现ajax跨域
- ZigBee开发(15)--组网实验点播
- 新手福音,机器学习工具Sklearn 中文文档 0.19版(最新)
- 冒泡排序(bubble sort)算法实现
- 自动化查询及增加配置参数功能
- Qt获取本机硬盘序列号,不受IDE硬盘与SCSI硬盘类型影响
- Discuz!论坛系统模板目录结构注释说明(以default模板为例)
- keil5c语言定义引脚,keil编写C程序是不是不能在函数内定义变量啊,求大神
- 【Android Tricks 6】ViewPager首页与尾页的滑动动作响应
- AcWing 120 防线
- linux第7章进程状态和控制
- 写的坦克游戏 希望对你有帮助
- DAY41:Cobalt Strike 工具使用
热门文章
- 南京廖华里mysql测试题1答案_MySQL数据库考试试题及答案
- 离线数仓 (十三) --------- DWD 层搭建
- jquery/jquery-3.5.1.min.js net::ERR_ABORTED 404 (Not Found)
- 桌面图标文件夹图标隐藏恢复
- Mathcad求解一元二次方程
- JS字符串截取 “指定字符” 前面和后面的内容!
- 2022蓝牙耳机大盘点测评,2022年最新蓝牙耳机排行榜
- Android尺寸标注设计大全和Android切图规范
- 爬取在行平台数据(1)——动态加载页面分析
- 同济大学符长虹教授作“基于计算机视觉的无人飞行器自主导航研究与应用”为题的报告