前言
学习Redis,那肯定不得不接触五个基础常用类型,当然初学的小朋友可不要和我一样,以为Redis只有五个基础数据类型,其实Redis 有 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询,只是前五个常用,嗯。。暂时我是这样理解的
一、String
String类型是Redis中最常用的数据类型了,基本上所有用过Redis的小伙伴都会过这个类型,所以也没啥好介绍的,就介绍一下和String相关的命令吧。
127.0.0.1:6379> flushall # 清空数据库内所有数据
OK
127.0.0.1:6379> set name cainiao # 添加key=name,value=cainiao的数据
OK
127.0.0.1:6379> exists name # 检查name是否存在
(integer) 1
127.0.0.1:6379> get name
"cainiao"
127.0.0.1:6379> strlen name # 查看name的长度
(integer) 7
127.0.0.1:6379> append name 110 # 追加字符110
(integer) 10
127.0.0.1:6379> get name
"cainiao110"
127.0.0.1:6379> append age 10 # 当所追加的key不存在的时候,创建一个age
(integer) 2
127.0.0.1:6379> get age
"10"
127.0.0.1:6379> get name
"cainiao"
127.0.0.1:6379> getrange name 1 3 # 截取String串
"ain"
127.0.0.1:6379> getrange name 3 2
""
127.0.0.1:6379> getrange name 3 5
"nia"
127.0.0.1:6379> setrange name 3 111 # 替换字符串
(integer) 7
127.0.0.1:6379> get name
"cai111o"
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 批量设置
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"
127.0.0.1:6379> mget k1 k2 k3 # 批量获取
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k3 v3 k4 v4 # 当批量设置时,只要其中一个设置出现问题,则全部失败,这是原子性
(integer) 0
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"
127.0.0.1:6379> getset test 123 # 先获取test,再赋值
(nil)
127.0.0.1:6379> getset test 456
"123"
127.0.0.1:6379> get test
"456"
上面是对Redis String 的赋值、获取、追加等,下面是累加操作
127.0.0.1:6379> set views 10 # 插入 view=10
OK
127.0.0.1:6379> get views
"10"
127.0.0.1:6379> incr views # 累加 10+1=11
(integer) 11
127.0.0.1:6379> get views
"11"
127.0.0.1:6379> decr views # 递减 11-1=10
(integer) 10
127.0.0.1:6379> decr views
(integer) 9
127.0.0.1:6379> get views
"9"
127.0.0.1:6379> incrby views 10 # 这个也是累加,不过是根据具体数值进行累加,如 9+10=19
(integer) 19
127.0.0.1:6379> get views
"19"
127.0.0.1:6379> decrby views 9 # 减少 19-9=10
(integer) 10
127.0.0.1:6379> get views
"10"
设置过期时间、不存在设置
127.0.0.1:6379> setex name 30 cainiao # set expire 设置name 30秒后过期
OK
127.0.0.1:6379> ttl name
(integer) 28
127.0.0.1:6379> ttl name
(integer) 23
127.0.0.1:6379> ttl name
(integer) 3
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> setnx name cainiao # set if not exist 如果不存在则设置成功
(integer) 1
127.0.0.1:6379> get name
"cainiao"
127.0.0.1:6379> setnx name redis # 因为那么已经存在,所以设置不成功,这个常常用在分布式的场景下
(integer) 0
127.0.0.1:6379> get name
"cainiao"
我认为下面这种方式并不是一个语法上的命令,而是结构上的去存储一个对象的办法,将key存储为user:1:name,就是{对象名}:{id}:{属性名},这样的key结构
127.0.0.1:6379> mset user:1:name cainiao user:1:age 18
OK
127.0.0.1:6379> keys *
1) "user:1:age"
2) "user:1:name"
127.0.0.1:6379> mget user:1:name user:1:age
1) "cainiao"
2) "18"
二、List
list 数据类型,学习过java的肯定是知道List的,类似于java中的list,都是存储一个集合,但是呢,它更像一个链表,如果是了解链表的小朋友,那一定是非常了解的,这就不得不感慨为啥大公司要基础扎实的程序员了,程序都是同的,基础扎实证明学什么都快,不过如果是不了解链表的小伙伴也不要绝望,我认为链表有点类似于下图
其实还是链表的样式,只不过被我去掉了指针相应的表示,这个list类型是依次从左至右的顺序,1,2,3,4,5,6…这样的下标方式,LPUSH插入的数据总是在第一个,RPUSH插入的数据总是在最后一个,是一个双向链表
下面就是List涉及到的相应命令了
127.0.0.1:6379> rpush list value1 # 右插入数据,新插入数据始终在最后一个
(integer) 1
127.0.0.1:6379> lrange list 0 -1 # 查看指定范围下标的数据,-1表示最后一个
1) "value1"
127.0.0.1:6379> rpush list value2 value3
(integer) 3
127.0.0.1:6379> lrange list 0 -1 # 左插入数据,新插入数据始终在第一个
1) "value1"
2) "value2"
3) "value3"
127.0.0.1:6379> lpush list value0
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "value0"
2) "value1"
3) "value2"
4) "value3"
127.0.0.1:6379> lpop list # 移除第一个元素
"value0"
127.0.0.1:6379> rpop list # 移除最后一个元素
"value3"
127.0.0.1:6379> lrange list 0 -1
1) "value1"
2) "value2"
127.0.0.1:6379> lindex list 0 # 查看指定下标的数据
"value1"
127.0.0.1:6379> lrange list 0 -1
1) "value1"
2) "value2"
127.0.0.1:6379> rpush list value3 value3 value3
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "value1"
2) "value2"
3) "value3"
4) "value3"
5) "value3"
127.0.0.1:6379> lrem list 1 value3 # 移除指定数量的指定元素,如此命令中移除一个value3的元素
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "value1"
2) "value2"
3) "value3"
4) "value3"
127.0.0.1:6379> lrem list 2 value3 # 移除指定数量的指定元素,如此命令中移除两个value3的元素
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "value1"
2) "value2"
127.0.0.1:6379> llen list # 查看指定list集合的数量
(integer) 2
127.0.0.1:6379> lpush list value0
(integer) 3
127.0.0.1:6379> rpush list value3 value4
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "value0"
2) "value1"
3) "value2"
4) "value3"
5) "value4"
127.0.0.1:6379> ltrim list 2 4 # 截取集合,下标以0开始
OK
127.0.0.1:6379> lrange list 0 -1
1) "value2"
2) "value3"
3) "value4"
127.0.0.1:6379> rpoplpush list list1 # 组合命令,意思是将集合list的最后一个元素list4转移到新的集合list1中
"value4"
127.0.0.1:6379> keys *
1) "list1"
2) "list"
127.0.0.1:6379> lrange list1 0 -1
1) "value4"
127.0.0.1:6379> lrange list 0 -1
1) "value2"
2) "value3"
127.0.0.1:6379> move list1 1 # 移除list1集合
(integer) 1
127.0.0.1:6379> keys *
1) "list"
127.0.0.1:6379> lrange list 0 -1
1) "value2"
2) "value3"
127.0.0.1:6379> lpush list value1 value0
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "value0"
2) "value1"
3) "value2"
4) "value3"
127.0.0.1:6379> lset list 3 setValue3 # 修改下标为3的item
OK
127.0.0.1:6379> lrange list 0 -1
1) "value0"
2) "value1"
3) "value2"
4) "setValue3"
127.0.0.1:6379> lset list 4 null # 当要修改的下标超过了当前的范围或者修改的集合不存在则报错,也就是说这个命令就是单纯的修改,没有添加
(error) ERR index out of range
127.0.0.1:6379> lset list0 0 test
(error) ERR no such key
127.0.0.1:6379> lrange list 0 -1
1) "value0"
2) "value1"
3) "value2"
4) "setValue3"
127.0.0.1:6379> linsert list after value1 value1-after # 插入item,在某个指定的item前后插入
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "value0"
2) "value1"
3) "value1-after"
4) "value2"
5) "setValue3"
127.0.0.1:6379>
127.0.0.1:6379> linsert list before value1 value1-before
(integer) 6
127.0.0.1:6379> lrange list 0 -1
1) "value0"
2) "value1-before"
3) "value1"
4) "value1-after"
5) "value2"
6) "setValue3"
127.0.0.1:6379> linsert list after value2 value2
(integer) 7
127.0.0.1:6379> lrange list 0 -1
1) "value0"
2) "value1-before"
3) "value1"
4) "value1-after"
5) "value2"
6) "value2"
7) "setValue3"
127.0.0.1:6379> linsert list after value2 value2-after # 当有同一个item的情况下,默认是在第一个item前后进行插入
(integer) 8
127.0.0.1:6379> lrange list 0 -1
1) "value0"
2) "value1-before"
3) "value1"
4) "value1-after"
5) "value2"
6) "value2-after"
7) "value2"
8) "setValue3"
上边的命令看起来其实并不友好,但是命令这个东西是有敲起来懂的会快一点,这样展示出来也能很详细的看到命令执行结果,就是需要一些耐心…总结一下,总共有如下几个命令:lpush,rpush,lrange,lpop,rpop,lindex,lrem,llen,ltrim,rpoplpush,lset,linsert。大概就这些,也可以直接在官网查询这些命令的用法。
三、Set
Set数据结构吧,就一个特点就概括了,无序且不重复
下面主要涉及到了这些命令:sadd,smembers,scard,srem,sismember,srandmember,smove,sdiff,sunion,sinter,下面看一下详细使用情况
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> sadd set value0 value1 value2 value3 value4 # 批量添加set类型元素
(integer) 5
127.0.0.1:6379> smembers set # 打印所有set下边的元素,是无序且不重复的
1) "value2"
2) "value0"
3) "value3"
4) "value1"
5) "value4"
127.0.0.1:6379> sismember set value0 # 判断set集合下某个值是否存在
(integer) 1
127.0.0.1:6379> scard set # 查看set集合中的个数
(integer) 5
127.0.0.1:6379> srem set value0 # 移除指定元素
(integer) 1
127.0.0.1:6379> scard set
(integer) 4
127.0.0.1:6379> smembers set
1) "value3"
2) "value1"
3) "value2"
4) "value4"
127.0.0.1:6379> srandmember set 2 # 随机取出指定数量的元素
1) "value4"
2) "value3"
127.0.0.1:6379> srandmember set 2
1) "value2"
2) "value4"
127.0.0.1:6379> smove set set1 value1 # 将指定元素移动到其他set集合中
(integer) 1
127.0.0.1:6379> smembers set
1) "value2"
2) "value3"
3) "value4"
127.0.0.1:6379> smembers set1
1) "value1"
# 清空所有数据,测试sdiff(差集),sinter(交集),sunion(并集)
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> sadd set 1 2 3
(integer) 3
127.0.0.1:6379> sadd myset 3 4 5
(integer) 3
127.0.0.1:6379> smembers set
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> smembers myset
1) "3"
2) "4"
3) "5"
127.0.0.1:6379> sdiff set myset
1) "1"
2) "2"
127.0.0.1:6379> sinter set myset
1) "3"
127.0.0.1:6379> sunion set myset
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
四、Hash
还是先写个人理解,这个有点像java中的一个map再嵌套一个map(禁止套娃…),redis中就是k-v的数据结构,在v中又加了一层k-v的数据结构,这样子有啥好处呢,其实就是为了对应有些需要存储类似于对象的数据,嗯…我就懂点java,我是这样理解的,主要涉及的命令其实真的和String类型很相似,就是加了个前缀h,大体命令有:
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> hset hash k1 v1 k2 v2 # 同String中set,不过可以设置多个值
(integer) 2
127.0.0.1:6379> hget hash k1 # 同String中get
"v1"
127.0.0.1:6379> hmset hash k3 v3 k4 v4 # 同String中mset
OK
127.0.0.1:6379> hmget hash k1 k2 k3 k4 # 同String中mget
1) "v1"
2) "v2"
3) "v3"
4) "v4"
127.0.0.1:6379> hlen hash # 同String中strlen
(integer) 4
127.0.0.1:6379> hdel hash k4 # 同String中move
(integer) 1
127.0.0.1:6379> hgetall hash # 得到所有的k-v
1) "k1"
2) "v1"
3) "k2"
4) "v2"
5) "k3"
6) "v3"
127.0.0.1:6379> hexists hash k4 # 同String中exists
(integer) 0
127.0.0.1:6379> hexists hash k3
(integer) 1
127.0.0.1:6379> hkeys hash # 获取所有的key
1) "k1"
2) "k2"
3) "k3"
127.0.0.1:6379> hvals hash # 获取所有的value
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> hset hash k4 3
(integer) 1
127.0.0.1:6379> hget hash k4
"3"
127.0.0.1:6379> hincrby hash k4 1 # 同String中 incrby
(integer) 4
127.0.0.1:6379> hincrby hash k4 3
(integer) 7
127.0.0.1:6379> hget hash k4
"7"
127.0.0.1:6379> hsetnx hash k4 1 # 同String中setnx
(integer) 0
127.0.0.1:6379> hget hash k4
"7"
127.0.0.1:6379> hsetnx hash k5 1
(integer) 1
127.0.0.1:6379> hget hash k5
"1"
127.0.0.1:6379> type hash # 查看hash是什么数据类型
hash
五、Zset
Zset我认为就是set的plus版本,在set的基础上加了一个下标管理可以用来排序,也就是有序set集合的意思,主要涉及的命令也比较少,就是增删改查,如:zadd,zrange,zrangebyscore,zrem,zcard,zcount,zrevrange,zrevrangebyscore,有一点要注意,它是有序set,那么它的元素值就是不可以重复的,但是下标是可以重复的
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> zadd zset 1 v1 2 v2 3 v3 # 添加元素,包括下标和元素值
(integer) 3
127.0.0.1:6379> zrange zset 0 -1 # 显示范围内的元素值,按从小到大的顺序
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> zrangebyscore zset 0 -1 # 显示范围内的元素值,按从小打大的顺序,-inf、+inf分别对应负无穷和正无穷,withscores表示输出下标
(empty array)
127.0.0.1:6379> zrangebyscore zset 0 5
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> zrangebyscore zset -inf +inf
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> zrangebyscore zset -inf +inf withscores
1) "v1"
2) "1"
3) "v2"
4) "2"
5) "v3"
6) "3"
127.0.0.1:6379> zcard zset # 查看zset集合的元素个数
(integer) 3
127.0.0.1:6379> zadd zset 6 v6
(integer) 1
127.0.0.1:6379> zcount zset 3 6 # 查看一定范围内的元素个数
(integer) 2
127.0.0.1:6379> zrem zset v6 # 移除指定元素
(integer) 1
127.0.0.1:6379> zrange zset 0 -1
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> zrevrange zset 0 -1 # 倒序输出
1) "v3"
2) "v2"
3) "v1"
127.0.0.1:6379> zrevrangebyscore zset +inf -inf withscores # 倒序输出
1) "v3"
2) "3"
3) "v2"
4) "2"
5) "v1"
6) "1"
六、三个特殊类型
既然把五个常用的基本数据类型给看了,那有三个特殊类型也一定要了解一下,那分别是Geospatial、Hyperloglog、Bitmap
1. Geospatial
直译应该就是地图类型吧,我们看一下官网说它是怎么工作呢?
sorted set使用一种称为Geohash的技术进行填充。经度和纬度的位是交错的,以形成一个独特的52位整数.
我们知道,一个sorted set 的double score可以代表一个52位的整数,而不会失去精度。 这种格式允许半径查询检查的1 +
8个领域需要覆盖整个半径,并丢弃元素以外的半径。通过计算该区域的范围,通过计算所涵盖的范围,从不太重要的部分的排序集的得分,并计算得分范围为每个区域的sorted
set中的查询。
总结一下其实就是Geospatial的底层是zset实现的,所以针对于zset的命令在Geospatial也是有用的,同时让我们看一下独属于Geospatial的命令吧,它的命令有:GEOADD,GEODIST,GEOHASH,GEOPOS,GEORADIUS,GEORADIUSBYMEMBER,一共有这六个,下面也着重看一下这六个命令的使用方法。
# 首先我们通过geoadd添加一些地理信息
# 有效的经度从-180度到180度。
# 有效的纬度从-85.05112878度到85.05112878度。
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> geoadd china:city 116.23128 40.22077 beijing 121.48941 31.40527 shanghai 119.48458 39.83507 qinhuangdao 113.27324 23.15792 guangzhou 113.88308 22.55329 shenzhen
(integer) 5
# 通过zset中的命令查看一下所有成员
127.0.0.1:6379> zrangebyscore china:city -inf +inf withscores
1) "shenzhen"
2) "4046340107163728"
3) "guangzhou"
4) "4046534010880445"
5) "shanghai"
6) "4054807796443227"
7) "beijing"
8) "4069896088584598"
9) "qinhuangdao"
10) "4070804144342304"
# geopos 查看特定元素的地理位置
127.0.0.1:6379> geopos china:city shenzhen guangzhou
1) 1) "113.88307839632034302"
2) "22.55329111565713873"
2) 1) "113.27324062585830688"
2) "23.1579209662846921"
# 查看两个地位之间的直径距离, km:千米、m:米、ft:英尺、mi:英里
127.0.0.1:6379> geodist china:city shenzhen guangzhou km
"91.8118"
127.0.0.1:6379> geodist china:city shenzhen guangzhou m
"91811.7949"
127.0.0.1:6379> geodist china:city shenzhen guangzhou ft
"301219.7997"
127.0.0.1:6379> geodist china:city shenzhen guangzhou mi
"57.0493"
# 查看以某个坐标为半径的所有元素,withcoord:同时显示地理位置、withdist:同时显示相差距离、withhash:以hash方式显示位置、count:设置显示限数
127.0.0.1:6379> georadius china:city 113 22 200 km
1) "shenzhen"
2) "guangzhou"
127.0.0.1:6379> georadius china:city 113 22 200 km withcoord
1) 1) "shenzhen"
2) 1) "113.88307839632034302"
2) "22.55329111565713873"
2) 1) "guangzhou"
2) 1) "113.27324062585830688"
2) "23.1579209662846921"
127.0.0.1:6379> georadius china:city 113 22 200 km withcoord withdist
1) 1) "shenzhen"
2) "109.7645"
3) 1) "113.88307839632034302"
2) "22.55329111565713873"
2) 1) "guangzhou"
2) "131.8129"
3) 1) "113.27324062585830688"
2) "23.1579209662846921"
127.0.0.1:6379> georadius china:city 113 22 200 km withcoord withdist withhash
1) 1) "shenzhen"
2) "109.7645"
3) (integer) 4046340107163728
4) 1) "113.88307839632034302"
2) "22.55329111565713873"
2) 1) "guangzhou"
2) "131.8129"
3) (integer) 4046534010880445
4) 1) "113.27324062585830688"
2) "23.1579209662846921"
127.0.0.1:6379> georadius china:city 113 22 200 km withcoord withdist withhash count 1
1) 1) "shenzhen"
2) "109.7645"
3) (integer) 4046340107163728
4) 1) "113.88307839632034302"
2) "22.55329111565713873"
127.0.0.1:6379> georadius china:city 113 22 200 km withcoord withdist withhash count 3 desc
1) 1) "guangzhou"
2) "131.8129"
3) (integer) 4046534010880445
4) 1) "113.27324062585830688"
2) "23.1579209662846921"
2) 1) "shenzhen"
2) "109.7645"
3) (integer) 4046340107163728
4) 1) "113.88307839632034302"
2) "22.55329111565713873"
# 以某个元素为中心点,半径为200km内的所有元素信息,其他参数和georadius一致
127.0.0.1:6379> georadiusbymember china:city shenzhen 200 km withcoord
1) 1) "shenzhen"
2) 1) "113.88307839632034302"
2) "22.55329111565713873"
2) 1) "guangzhou"
2) 1) "113.27324062585830688"
2) "23.1579209662846921"
# 将地理经纬度由hash的方式显示,不常用,我也没有深入了解,有兴趣的小伙伴可以看官网
127.0.0.1:6379> geohash china:city beijing
1) "wx4sucvncn0"
2. Hyperloglog
这里涉及到了一个基数的概念,这个应该都懂,我简单解释一下,不理解的可以百度,其实就是在多个集合中去重的意思,类似于set集合,不可以有重复的数据,比如两个集合a{1,2,3,4,5,3},b{3,1,4},最后这基数后一共有五个数据{1,2,3,4,5}
Hyperloglog就是基于基数统计算法,可用于网站UV访问量这类的业务中,有一定的误差,0.81%左右,它涉及的命令就比较少了,如:pfadd,pfcount,pfmerge
127.0.0.1:6379> pfadd hyper 1 2 3 4 5 # 创建Hyperloglog并添加元素
(integer) 1
127.0.0.1:6379> pfadd hyper1 2 4 6
(integer) 1
127.0.0.1:6379> pfcount hyper hyper1 # 查看hyper和hyper1两个集合的元素个数,去掉重复的
(integer) 6
127.0.0.1:6379> pfcount hyper
(integer) 5
127.0.0.1:6379> pfcount hyper1
(integer) 3
127.0.0.1:6379> pfmerge hyper2 hyper hyper1 # 合并两个集合hyper,hyper1
OK
127.0.0.1:6379> keys *
1) "china:city"
2) "hyper2"
3) "hyper1"
4) "hyper"
127.0.0.1:6379> type hyper2 # Hyperloglog底层数据类型是string
string
127.0.0.1:6379> get hyper2
"HYLL\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80A\xee\x84H#\x80SQ\x80Mt\x80Q,\x8c@\xcf\x84C\""
127.0.0.1:6379> type china:city # geospatial底层数据类型是zset
zset
127.0.0.1:6379> pfcount hyper2
(integer) 6
通过上段代码也不难发现,redis数据类型只有五种数据类型,其他三种特殊数据类型都是基于基本类型的数据类型进行创建的。
3. Bitmaps
Bitmaps其实就是一个位图,存放的value是0 1这样的数据结构,它的应用场景也比较有特点,特别适合于两种状态这样的应用场景,比如是否打卡、是否登录等。它所涉及的命令只有三个:setbit、getbit、bitcount
127.0.0.1:6379> flushall
OK
# 设置一周的打卡情况,0:为默认未打卡;1:代表打卡
127.0.0.1:6379> setbit bitmaps 0 0
(integer) 0
127.0.0.1:6379> setbit bitmaps 1 0
(integer) 0
127.0.0.1:6379> setbit bitmaps 2 0
(integer) 0
127.0.0.1:6379> setbit bitmaps 3 1
(integer) 0
127.0.0.1:6379> setbit bitmaps 3 0 # 重复设置的话,是直接覆盖
(integer) 1
127.0.0.1:6379> getbit bitmaps 3
(integer) 0
127.0.0.1:6379> setbit bitmaps 4 1
(integer) 0
127.0.0.1:6379> setbit bitmaps 5 1
(integer) 0
127.0.0.1:6379> setbit bitmaps 6 0
(integer) 0
127.0.0.1:6379> bitcount bitmaps # 统计集合中有多少为1的记录
(integer) 2
结语
自此,Redis的数据类型大概就这些了,并不复杂,当然也正因为Redis结构简单所有才会达到读11000/s,写81000/s的速度,下一节是Redis事务