Redis(二)类型-string(字符串,数值和bitmap),list,set,hash,sorted_set

redis-cli启动客户端

上节已经安装了redis-server,并配置了环境变量和服务;
redis-cli -h可以查看帮助文档,如果部署了多个redis-server,则redis-cli -p port通过端口区分即可
redis默认是16个库,0~15号,可以通过配置文件修改数量,各个库相互独立.
可以启动的时候-n 指定库,也可以进入后select n 选择第几号库
进入redis-cli后,可输入help查看帮助文档

127.0.0.1:6379> help
redis-cli 5.0.5
To get help about Redis commands type:
      "help @<group>" to get a list of commands in <group>
      "help <command>" for help on <command>
      "help <tab>" to get a list of possible help topics
      "quit" to exit

To set redis-cli preferences:
      ":set hints" enable online hints
      ":set nohints" disable online hints
Set your preferences in ~/.redisclirc

在这里插入图片描述

String类型

基本操作:字符串和数值

可以通过 help @string查看关于string的各种操作命令,这些操作都是原子的
常用操作:

设值 set k1 123
获取 get k1
设多个值 mset k2 v2 k3 v3
获取多个值 mget k2 k3
拼接 append k1 " world"
获取指定索引段 getrange k1 0 3
从指定索引开始设值 setrange 3 hello
查看长度 strlen k1
设置新值,返回旧值 getset k1 world
同时设置多个值NX msetnx k1 a k2 b

数值相关的:

自增1 incr k1
自增指定整数值 incrby k1 3
自减1 decr k1
自减指定整数值 decrby k1 3
自增指定小数 incrbyfloat k1 1.5

自增-1其实就是自减1了嘛,所以没有自减指定小数也无所谓
自减的应用场景:秒杀抢购系统,规避对数据库的事务操作,二十用redis代替

还有bit相关的下面单独拿出来说

正反向索引

假如一个字符串"tom",正向索引从左到右0,1,2 逆向索引从右到左-1,-2,-3
所以getrange k1 0 -1就是获取整个字符串,详单与get k1

0
t
1
o
2
m
-3
-2
-1

可以help set查看set的说明:

127.0.0.1:6379> help set

  SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
  summary: Set the string value of a key
  since: 1.0.0
  group: string

NX|XX

  • NX:只能新建key;如果key不存在则设置成功,否则设置失败,用于分布式锁
    如果set k1 v11 nx,发下返回值是nil,然后再get k1发现它的值还是v1,没设值成功
  • XX:只能更新key,如果key存在则设置成功,否则设置失败

key是个对象,存储了type和encoding,length

key是个object,里面有:

  • 存储对应value的type
    type k1查看一个键值对的value类型,根据命令的分组,string分组下的一定是string类型
  • 编码encoding,通过object查看,可能有三个编码:int embstr raw
    mset k1 123 k2 hello
    这时type k1/k2都是string,但是object encoding k1 的结果是int
    key中的encoding只是为了方便操作时的判断,加快速度;并不会真的编码,因为redis存储的是byte[]
    加速体现在:如果encoding不是int,则incr等操作时,不进行类型转换的尝试,直接返回错误

一些操作可能会改变encoding:

这个encoding就是为了方便一些操作

127.0.0.1:6379> set k1 9
OK
127.0.0.1:6379> OBJECT encoding k1 
"int"
127.0.0.1:6379> STRLEN k1
(integer) 1
127.0.0.1:6379> APPEND k1 999
(integer) 4
127.0.0.1:6379> get k1
"9999"
127.0.0.1:6379> OBJECT encoding k1
"raw"
127.0.0.1:6379> incr k1
(integer) 10000
127.0.0.1:6379> object encoding k1
"int"
127.0.0.1:6379> STRLEN k1
(integer) 5

二进制安全

redis进程与外界(比如client)交互的时候,是通过字节数组,字节流;
redis保存的是字节数据,不会真的去编码encoding,防止各个语言客户端对于一些类型(比如数字)的理解不同而造成的编码问题.
key中的encoding只是为了方便操作时的判断
中文的长度,根据shell工具(客户端)的编码而定:utf8编码是3个字节,gbk编码是2个字节
redis默认只识别ASCII码,超出了就按照16进制显示
如果启动时带着–raw redis-cli --raw 则会格式化中文

bitmap

一个字节有8个二进制位,前面说的string的正反向索引,是面向字节的,二进制位也有自己的索引-offset,在多个字节间从0开始从左到右依次递增
一般start end指字节的索引,offset指位的索引
最小的分配单位时1字节,不够再扩容,第二个字节的offset从8到15

字符集ASCII 0xxxxxxx (第一个是0)
扩展:其他字符集不再对ASCII重新编码

设值 SETBIT key offset value
查找指定字节索引范围的第一个指定bit的bit索引 BITPOS key bit [start] [end]
统计1的次数 BITCOUNT key [start end]
按位操作(与 或 非 异或 and or not xor),结果存储位destkey BITOP operation destkey key [key … ,not运算只能是1个key

bitmap的使用场景:

  • 用户系统,统计用户登录天数,且窗口随机:
    如果用传统的MySQL思路,搞张表记录用户的登陆信息,每条记录的日期至少4个字节,且数据量大时很慢
    假如使用bitmap统计,一年366天,我们46个字节的bitmap就可以统计一个用户一年的登录情况,key时用户,value时登录情况,第几天登录了就把对应offset设为1
    统计最近16天的登录次数:bitcount k1 -1 -2
  • 电商系统,活动送礼物,假设一共2亿注册用户,要准备多少礼物?
    众所周知,用户分为 僵尸用户,冷热用户/忠诚用户,所以统计活跃用户就很关键.
    活跃用户统计:随机窗口,例如统计1号和2号期间登录过的用户数
    bitmap统计,key是日期,value表示用户(每个用户对应其中一位),然后指定的key做或运算,又能达到去重的效果
    setbit 20200301 1 1
    setbit 20200302 1 1
    setbit 20200302 7 1
    统计活跃用户:
    bitop or k1 20200301 20200302
    

List

像是双向链表+数组的结合体
list中 每个元素也有正负索引,值可以重复,
key中有指向head和tail的属性

help @list
常用命令:

  • lpush 从左边,即头部插入数据 lpush k1 a s d -> [d,s,a]
  • rpush 从右边,即尾部插入数据 rpush k2 a s d -> [a,s,d]
  • lpop 从左边弹出一个元素
  • rpop 从右边弹出一个元素
  • lindex key index 查看指定index的元素
  • lrange key start stop 查看 从start到stop索引的元素
  • lset k1 index value 修改指定index的元素值
  • lrem key count value 从左边开始计数,移除count个value(list中的元素可重复) (如果count是负数,就相当于从右边开始移除-count个)
  • linsert key before|after pivot value 在左边第一个pivot元素的 前|后 插入元素
  • llen key 链表长度
  • blpop key [key…] timeout 阻塞弹出元素,有点像Java的BlockingList;timeout是0的话,取不到数据时就一直阻塞
  • ltrim key start stop 只保留start到stop的元素,其他的删除

使用lpush,rpush,lpop,rpop 可以实现栈和队列
加入blpop后,可以实现阻塞队列,单播队列

hash

就像Java的hashmap

help @hash
常用命令:

  • hset key field value 赋值键值对
  • hmset key field value [field value…] 设多个键值对
  • hget key field 获取某个field
  • hmget field [field…] 获取多个field
  • hkeys key 查看所有key,即field
  • hvals key 查看所有value
  • hgetall key 查看所有键值对
  • hincrby key field number 给某个字段自增一定值,可以是负数;需要该字段值是整数
  • hincrbyfloat key field number 给某个字段自增一定值,可以是负数;

hincrby 可以用于点赞,浏览量等

set

就像Java中的hashset,无序,去重
set也有正负索引

help @set
常用命令:

  • sadd key member [member…] 添加
  • smembers key 查看所有元素
  • srem key member [member…] 删除
  • sinter key[key…] 取交集
  • sinterstore destination key[key…] 取交集,并存储到destination
  • sunion key[key…] 取并集
  • sdiff key[key…] 取左差集,sdiff k1 k2 去除k1中的 “k2中没有” 的元素
  • srandmember key [count] 随机事件,随机取出count个元素;
    如果是正数,取出不重复的count个元素,但不会超过set的size
    如果是负数,取出可能重复的-count个元素,可以超过set size
    如果是0,就没有动作
  • spop key [count] 随机弹出count个元素,不会超过set的size

srandmember.spop 可以用来简单的公平抽奖
一些需要加权重的抽奖,还是需要写代码实现了

sorted_set

去重,排序
既然能否排序,在给出元素的同时,也伴随着一个分值–即根据啥排序;如果分值都一样,那么按字典顺序排序
也有正负索引

help @sorted_set
常用命令:

  • zadd key score member [score member…] 添加
  • zrange key start stop [withscores] 正向排序查看排名start到stop的元素[带着分值]
  • zrangebyscore key min max 取出分值在min~max间的元素
  • zrevrange key start stop 逆向排序查看排名start到stop的元素
  • zscore key member 查看分数
  • zrank key member 查看排名
  • zincrby key number member 分值自增
  • ZUNIONSTORE destination numkeys key [key …] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] 取并集,默认权重都是1,聚合方式为sum
  • ZINTERSTORE destination numkeys key [key …] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] 取交集

sorted_set排序是怎么实现的?

skip list 跳跃表 (类平衡树?)
这样设计,增删改查的平均速度 相对更优,稳定
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值