Loading... # redis数据类型与基础操作 ## 简介 Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。 ## redis实例 ![01.png][1] redis是单线程、单进程、单实例的。一台服务器可以开启多个redis实例,通过端口区分。可以通过 ``` redis-cli -p 端口号 ``` 来连接不同的实例,如果不指定端口号,默认是6379 redis通过epoll来读取client请求,因为是单线程、单进程,所以保证每个连接内命令的顺序一致,也就是说客户端处理好线程安全问题,交给redis之后一定是安全的。每个redis默认会生成16个库0-16,可以通过配置文件修改。可以通过 ``` redis-cli -n (0-16) ``` 来选择不同的库进入,或者在进入之后通过 ``` select (0-16) ``` 来切换库 ## 数据类型 redis通过key-value的形式存放数据,value有String、List、hash、Set、sorted_set多种类型。其中key上面会保留一些属性,例如: 1. type value的类型,可以通过 ``` type key ``` 来获取value的数据类型 2. Object encoding value的编码,比如embstr(字符串),int(数字),可以通过 ``` Object encoding key ``` 命令来获取。该方式可以加快处理速度,比如我的编码是embstr,当我执行累加操作的时候,发现不是int,就直接抛出异常, 不用再去判断value是否是数字了。每次执行成功执行string或int的操作之后,都会把编码保存在key中。 ### String类型 ![02.png][2] String类型实际存储的是byte也就是字节,二进制安全,不涉及到编码问题。因为是byte所以redis的String实际上包含,字符串,数值,bitmap三种类型。 - 字符串 针对字符串的操作有 写入数据 ``` set key value ``` 获得数据 ``` get key ``` 追加数据 ``` append key value ``` 替换字符串中的字符 ``` setrange key offset value ``` 获取字符串中的字符,字符串为双向索引,从前到后为0-n,从后到前为-1-(-n) ``` getrange key start end ``` 获取字符串长度(实际获取的是字节的数组的长度,一个中文有可能长度为2或3) ``` strlen key ``` - 数值 针对数值的操作有 自增1 ``` incr key ``` 自减1 ``` decr key ``` 增加n ``` incrby key n ``` 减少n ``` decrby key n ``` - bitmap bitmap,针对位进行操作,在redis中,每个字节都有自己的下标,一个字节有8位二进制,同样的每一位也有自己的下标,位的下标从0开始,一个字符串中,第一个字节是0-7,第二个字节就是8-15,可以通过 ``` setbit key offset value ``` 来修改key所对应的value的offset位的下标的值,如执行 ``` setbit k1 1 1 setbit k1 7 1 setbit k1 9 1 setbit k1 14 1 get k1 ``` 此时k1的所对应的二进制值为:0100 0001 0100 0010,输出的value就是"AB" 统计某几个字节二进制位为1的数量 ``` bitcount key start end ``` 其中start,end为字节的序号 寻找某个二进制位,第一个出现的位置 ``` bitpos key 1 [start] [end] ``` 寻找二进制1出现的位置,start,end为字节下标 位的操作,与或非异或等 ``` bitop and andkey k1 k2 ... ``` k1,k2等做与操作,结果保存为andkey,同理还有或操作 ``` bitop or orkey k1 k2 ... ``` bitmap应用场景 1. 有用户系统,统计用户登录天数,且窗口随机 365天每天占一位,每个用户是一个key,当某个用户登录后,该key对应的位数设置为1 ``` setbit sean 1 1 setbit sean 7 1 setbit sean 364 1 STRLEN sean BITCOUNT sean -2 -1 ``` 每个字节是8位,所以该命令返回结果为最后16天中,该用户登录了几天。 2. 京东618做活动:送礼物大库备货多少礼物(统计活跃用户) 每个用户占一位,有多少用户占多少位,每个日期是一条记录,如果用户登录,将该天所对应的记录的对应位设置为1,之后将n 个时间做或操作,只要登录过一次就是1,然后统计出结果中二进制1的数量,就是该时间段内的活跃用户数。 ``` setbit 20190101 1 1 setbit 20190102 1 1 setbit 20190102 7 1 bitop or destkey 20190101 20190102 BITCOUNT destkey 0 -1 ``` ### List类型 ![03.png][3] List是以链表形式存储,可重复,有序。有栈,队列,数组,阻塞队列等多种表现形式。List的key中会保存head和tail两个属性,分别表示头指针与尾指针。 #### 栈或队列操作 ``` LPUSH k1 a b c d e f # 从左侧放入a b c d e f ``` 从左侧放入(头部),先放入a,再在a的左边放入b以此类推,因此链表中的真实顺序为f,e,d,c,b,a ``` LPOP k1 ``` 从头部弹出一个元素,第一次执行应该弹出f ``` RPUSH k2 a b c d e f # 从又侧放入a b c d e f ``` 从右侧放入(尾部),先放入a,再在a的右边放入b以此类推,因此链表中的真实顺序为a,b,c,d,e,f 同向命令为栈,反向命令为队列(左放左取或右放右取为栈,左放右取或右放左取为队列) #### 数组操作 ``` LRANGE key start end ``` 取得List中从start到end的所有元素 ``` LINDEX key index ``` 取得下标为index的元素 ``` LSET key index value ``` 将下标为index的元素的值设置为value ``` LREM key count value ``` count为正数:从左侧开始,移除count个值为value的元素 count为负数:从右侧开始,移除count个值为value的元素 ``` LINSERT key before|after pivot value ``` 在第一个值为pivot的元素的before(前)/after(后),插入值为value的元素 ``` LLEN key ``` 获取List的长度 ``` LTRIM key start stop ``` 删除start与stop两端的两个元素,也就是start-1与stop+1 #### 阻塞队列操作 ``` BLPOP k1 k2 ... timeout # 左侧 BRPOP k1 k2 ... timeout # 右侧 ``` 阻塞弹出,当List为空的时候阻塞timeout时间,直到有值的时候弹出,timeout为0的时候表示没有值就一直阻塞。 ### hash类型 hash类型相当于map,储存的value为key-value形式。 ![04.png][4] #### hash的操作 ``` HSET key field value ``` 添加一个field-value键值对 ``` HMSET key f1 v1 f2 v2 ... ``` 添加多个键值对 ``` HGET key field ``` 取出key为field的键值对的value ``` HMGET key f1 f2 ... ``` 取出多个值 ``` HKEYS key ``` 取出所有的field ``` HVALS key ``` 取出所有field对应的value ``` HGETALL key ``` 取出所有field-value键值对 ``` HINCRBYFLOAT key field increment ``` 对field对应的value追加浮点精度的increment的值,increment为负数表示做减法,不涉及到浮点值可以直接使用HINCRBY命令。 ### Set类型 Set是一个去重,无序,随机(放入的多少不同,元素存储的顺序不同)的集合。 ![05.png][5] Set可以做集合操作(交集、并集、差集),也可以做随机事件。 #### Set相关操作 ``` SADD key m1 m2 ... ``` 向Set中添加元素 ``` SMEMBERS key ``` 获取Set中所有元素 ``` SREM key m1 m2 ... ``` 移除Set中的元素 ``` SINTER k1 k2 ... ``` 多个Set做交集,并返回结果 ``` SINTERSTORE destination k1 k2 ... ``` 多个Set做交集,结果保存在destination中,结果也是一个Set ``` SUNION k1 k2 ... ``` 多个Set做并集 ``` SDIFF k1 k2 ... ``` 多个Set做差集,想取到谁的数据把谁放在左边,右边的作为参考,也就是说k1 k2不同于k2 k1。 ``` SRANDMEMBER key count ``` 随机事件 当count为正数:取出一个去重的结果集,不能超过已有集 当count为负数:取出一个带重复的结果集,一定满足你要的数量 当count为0:不返回 应用场景:抽奖,奖品总共有10个,当人数比奖品多时,可以用count为正数,取前10个不重复的人获得奖品,当人数比奖品少的时候,可以将count设置成负数,取10个人,每个人有可能获得多个奖品。 ``` SPOP key count ``` 从Set中取出count个元素,取出数据不放回 应用场景:年会抽奖,多个奖项但是每个人只能参加一种。 ### sorted_set类型 sorted_set是一个去重,有排序规则的集合,与Set一样可以进行集合相关操作。因为有排序规则,所以存储数据有两个维度,分别是元素与分值,物理内存左小右大,当分值相同的情况下,按字典序排。 ![06.png][6] #### sorted_set相关操作 ``` ZADD key score1 member1 score2 member2 ... ``` 添加元素和分值 ``` ZRANGE key start stop [WITHSCORES] ``` 获取所有start到end之间的所有元素,WITHSCORES表示是否返回分值 ``` ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] ``` 取出分值在min与max之间的所有元素 ``` ZREVRANGE start stop [WITHSCORES] ``` 反向获取start到end之间的所有元素(REV表示反向) ``` ZSCORE key member ``` 通过元素取出分值 ``` ZRANK key member ``` 通过元素取出排名 ``` ZINCRBY key increment member ``` 将member元素的分值增加increment 应用场景:歌曲排行榜,反向取前n个,通过点击、下载等因素,动态增加元素分值 ``` ZUNIONSTORE destination numkeys k1 k2 ... [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] ``` numkeys表示要做操作的key的数量,weight是权重,顺序与key对应有几个写几个,分数会根据权重计算相应比值(weight1是1,weight2是0.5,那么,做并集操作时,k1的分值不变,k2的分值要除以2),AGGREGATE表示并集分值的操作,是相加还是取最大值或最小值(默认是sum),结果保存在destination中,示例: ``` ZUNIONSTORE unkey 2 k1 k2 WEIGHTS 1 0.5 AGGREGATE MAX ``` sorted_set的存储结构是一个跳跃表,保证增删改查与排序的消耗平均值相对最优。 ![跳跃表简单图示][7] [1]: https://www.princelei.club/usr/uploads/2019/11/3853555343.png [2]: https://www.princelei.club/usr/uploads/2019/11/1924639956.png [3]: https://www.princelei.club/usr/uploads/2019/11/3878219691.png [4]: https://www.princelei.club/usr/uploads/2019/11/3173523379.png [5]: https://www.princelei.club/usr/uploads/2019/11/3919478404.png [6]: https://www.princelei.club/usr/uploads/2019/11/1841223606.png [7]: https://www.princelei.club/usr/uploads/2019/11/1444839415.png Last modification:June 11th, 2020 at 06:15 pm © 允许规范转载