Redis入门篇(1)-类型技能

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/JavaMrZhang/article/details/89881221

字符串

首先Redis数据存储都会以key value 的形式进行存放, 所有的key都是字符串类型。此处所说的类型特指的是value中存放的类型。下文所讲的hash、列表都是基于value上进行讲解的。Redis会根据传入字符串类型规则进行判断,并采取相应的内部编码进行存储。数值型会采用8个字节的长整型进行编码存储,小于等于39个字节的字符串采用emstr编码存储,大于39字节的字符串采用raw编码存储。如果需要查看该键对应值的存储类型可运行object encoding k1命令。

  • 常用写命令
// 1. 设置键:k1  值 v1
set k1 v1 
// 2. 与上一个set k1 v1 命令一致,只不过键k1不存在的时候才能设置成功,存在的话将会设置失败
set k1 v1 nx
// 另一种写法
setnx k1 v1 
// 3. 键k1 必须存在才能设置成功
setxx k1 v1 xx 
// 4. 给键 k1 设置 10秒的过期时间
set k1 v1 ex 10
//另一种写法:setex k1 10 v1 
// 5. 给键 k1 设置 1000 毫秒的过期时间
set k1  v1 px 1000
// 6. 批量设置键值
mset k1 v1 k2 v2 k3 v3 
// 7. 对k1中的数值进行自增操作,如果k1中的值类型不为数值类型将会返回错误,如果不存在键k1,会按照初始值0进行自增
incr k1 
// 8. 对k1中的值按2的长度进行自增操作。
incrby k1 2 
  • 常用读命令
// 1. 获取键 k1 的 值
get k1 
// 2. 批量获取 k1,k2,k3 的值
mget k1 k2 k3 k4 

注意:key一般我们都会采用业务名:对象名:属性名的方式进行命名。


哈希

哈希类型在Redis中value是以{{key,value},{key,value}}的形式存储,我们通过字符和哈希类型的存储模型图来更直观的认识它们两者之间的关系,如图1-1
图1-1

Redis对于哈希类型的存储会根据哈希类型个数(对应图中的field个数)采取不同编码进行存储。如果哈希类型个数小于hash-max-ziplist-entries(默认512个)且所有值的(对应图中的value)存储大小都小于hash-max-ziplist-value(默认64字节)那么会使用更加紧凑的ziplist编码进行存储。当无法满足ziplist条件的时候会采用hashtable编码方式进行存储。因为在节省内存方面ziplist比hashtable更优秀,但如果数据量上来后检索效率不及hashtable。

  • 常用写命令
// 1. 给regsiter:user:1 添加一对field:value
hset register:user:1 name zhangmj
//2. 给register:user:1 field(age)的value 增加2 
hincrby register:user:1  age 2
//3. 批量给regist:user:1 设置多个field-value
hmset register:user:1 name 'zhangmoujiang' age 12 
//4. 删除 register:user:1 的name
hdel register:user:1 name
  • 常用读命令
// 1. 获取 register:user:1 的name的value
hget register:user:1 name
// 2. 批量获取 register:user:1 多个field的value
hmget register:user:1 name age 
// 3. 获取 register:user:1对应所有field
hkeys register:user:1
// 4. 获取 register:user:1 对应所有field的value
hvals register:user:1
// 5. 获取 register:user:1 所有 field 和value
hgetall register:user:1 

列表

Redis中列表类型的存储模型如图1-2:
图1-2
列表类型中value最多的存储元素为2^32-1个,可重复。value元素的内部编码根据元素个数和大小会采取ziplist和linkedlist两种编码方式进行存储。当value元素个数小于list-max-ziplist-entries(默认512),同时value中每个元素的大小小于list-max-ziplist-value(64字节)会采取ziplist进行编码。当无法满足ziplist的条件会采取linkedlist编码。ziplist编码对数据进行压缩以减少内存,而linkedlist采用链表的数据结构来存储数据。据说Redis3.2 版本之后提供了一个更合理的内部编码 quicklist,它结合ziplist和linkedlist两者的优势。

  • 常用写命令

为了行文方便 对于从左往右我们用此图标进行标记:➡️, 从右往左用此图标标记⬅️,列表都特指user:1:message

//1. ⬅️给列表插入元素
rpush user:1:message 'piaoliang' '帅气'
//2. ⬅️给列表插入元素
lpush user:1:message 'xx1' 'xx2'
//3. 在元素xx2 之前插入 xx1.5
linsert user:1:message before 'xx2' 'xx1.5'
//4. 在元素xx2 之后插入 xx3
linsert user:1:message after 'xx2' 'xx3'
//5. 从列表左侧弹出元素
lpop user:1:message
//6. 从列表右侧弹出元素
rpop user:1:message
//7. 从左侧弹出元素,如果列表不为空立即弹出,如果列表为空将阻塞3s后返回。
//该命令的基本格式:blpop key [key] timeout ,如果当timeout设为0且列表为空时,客户端运行此命令将会一致阻塞等待下去。
//如果设置了多个key,只要有一个key列表中有元素会立即返回
blpop user:1:message 3 
//8. 同brpop 只不过是 从右侧弹出元素
brpop user:1:message 3


// 9. 从左往右删除列表中等于xx2的2个元素
// 该命令的基本格式为:lrem key count vlaue
// 其中 count > 0 会从左往右删除count个等于value的元素
// count < 0 则会从右往左删除count个等于value的元素
// count =0 则会删除列表中所有等于value的元素
lrem user:1:message 2 xx2
// 10. 保留列表中第2个元素和第4个元素,其他全删除
ltrim user:1:message 1 3 
// 11. 将列表中的第1个元素修改为xxx0
lset user:1:message 0 xxx0

  • 常用读命令
//1. ➡️ 获取 第1个和第2个元素。 
lrange user:1:message  0 1 
//2. ⬅️获取第1个和第2个元素
//  假设列表元素为 g,f,h,k ,那么会获取 h,k 的元素
lrange user:1:message  -1 -2
//3. 获取列表中从右边数,第1个元素
lindex user:1:message -1
//4. 获取user:1:message列表元素的长度
llen user:1:message
// 其中➡️列表元素索引下标 [0,N-1] , ⬅️列表元素索引下标:【-1,-N】N 为列表元素个数
  • 应用场景
  1. 通过lpush + brpop 命令 实现消息队列。
  2. 每个用户都有属于自己的文章列表,需要分页显示各个用户的文章列表。

集合

集合类型的元素是可以重复的,如图1-3为集合类型的存储模型图:
图1-3
集合类型的内部编码有两种:

  1. intset, 当集合类型为整数且数量小于set-max-inset-entries(默认512),会采取该编码方式
  2. 当无法满足intset编码的条件会采取hashtable
  • 常用的写命令
// 1.添加tag1 、tag2 元素
sadd user:1 tag1 tag2 
// 2.删除tag2 元素,返回删除成功的个数
srem user:1 tag2 
// 3.从集合中随机弹出一个元素 / 从集合 随机弹出 n 个元素
spop user:1 
// 4. 将集合【user:1】和【user:2】交集结果存放到destination
sinterstore destination user:1 user:2
// 5. 集合【user:1】 和 集合【user:2】并集结果存放到destination
sunionstore destination user:1 user:2
// 6. 集合【user:1】 和 集合【user:2】差集结果存放到destination
sdiffstore destination user:1 user:2
  • 常用的读命令
// 1.计算元素个数
scard user:1 
// 2.集合中是否存在tag3元素
sismember user:1 tag3
// 3.从集合随机返回一个元素 / 从集合随机返回2个元素
srandmember user:1 / srandmember user:1 2
// 4.获取集合中的所有元素,返回的结果是无序的
smembers user:1

// 5.求 集合【user:1】 和 集合【user:2】的交集
sinter user:1 user:2
// 6.求 集合【user:1】 和 集合【user:2】的并集
sunion user:1 user:2
// 7.求集合间的差集,即:user:2 集合的元素不在user:1中
sdiff user:2 user:1

注意:当集合的元素过多的时候,使用smembers命令会有损性能,建议使用sscan命令来完成。


有序集合

有序集合类型的存储模型如图1-4:
图1-4
它可以类比集合类型和哈希类型的组合,其中value中包含两个主要的字段score和member,member中元素的值不能够重复,而score中元素的类型为整型值能够重复。通过score中元素的值我们能够对member中的元素进行排序。
内部也采用了两种编码:

  1. ziplist (压缩列表)
  2. skiplist (跳跃表)
  • 写操作命令
// 1. 添加集合成员 ,(85 、 zmj)
zadd users 85 zmj
// 2. 添加集合成员 ,存在才能设置成功
zadd users XX 87 zhangmoujiang
// 3. 添加集合成员,不存在才能设置成功
zadd users NX 87 zhangmoujiang
// 4. 删除集合内成员 caonimei
zrem users caonimei
// 5. 给成员xunini增加 1分,如果没有成员会自动添加
zincrby users 1 xuxnini 
  • 读操作命令
// 1. 获取集合内成员数量
zcard users
// 2. 获取集合内zmj成员的分数
zscore users zmj
// 3. 获取集合内chenxiongshun成员分数的排名(分数从低到高)
zrank users chenxiongshun
// 4. 同zrank一样 (分数从高到低)
zrevrank users chenxiongshun
// 5. 返回指定排名的范围的成员(分数从低到高)
zrange users 0 2 [withscores]
// 6. 同zrange一样 (分数从高到低)
zrevrange users 0 1 [withscores]
// 7. 按照指定分数从低到高返回成员
// 基本格式 zrangebyscore key min max [withscores] [limit offset count]
zrangebyscore users 50 90
// 8. 返回指定分数的范围内的成员个数
zcount users 0 100

几个管理键的常用命令

//1. 当前数据库的键数量
dbsize
//2. 随机返回当前数据的一个键
randomkey
//3. 设置键key1 20 秒过期,如果键不存在返回结果为0。
//某个键设置了过期时间,然后执行了set命令,那么该键的过期时间会被清除。
expire key1 20 
//4. 查看key1键还剩几秒过去,返回数字的单位为秒。返回-2 表示已过期
ttl key1
//5. 移除键key1的过期时间
persisit  key1 
//6. 获取所有键,keys后面可接类正则的表达式来匹配键的名称
keys * 
//7. 选择0号数据库,redis中默认有16个数据库 ,编号从0开始...
select 0
//8. 清除当前数据库数据
flushdb
//9. 清除所有数据库数据
flushall

书写技术文章是一个循序渐进的过程,所以我不能保证每句话、每行代码都是对的,但至少能保证不复制、不粘贴,每篇文章都是自己对技术的认识、细心斟酌总结出来的。乔布斯说:我们在这个星球上的时间都很短,很少有机会去做几件真正伟大的事情,同时要做得好,我必须要趁我还年轻的时候完成这些事。
其实我想说的是,我是一枚程序员,我只想在有限的时间内尽可能去沉淀我这一生中所能沉淀下来的东西


清山绿水始于尘,博学多识贵于勤。

我有酒,你有故事吗?

微信公众号:「Java锦囊」。

欢迎一起谈天说地,聊Java。


猜你喜欢

转载自blog.csdn.net/JavaMrZhang/article/details/89881221