目录
1.redis官网
2.redis-benchmark使用
3.redis指令
4.String数据类型
5.List数据类型
6.set(集合)
7.hash类型
8.zset(有序集合)
9.三种特殊的数据类型
9.1 geospatial地理位置
9.2hyperloglog基数统计
9.3Bitmap位运算
10.Redis事务
12.Redis监控(乐观锁)
Redis命令中心(Redis commands) -- Redis中国用户组(CRUG)
redis是一个单线程的,且与网络的带宽有关,底层是c语言写的,原子性的操作,不区分大小写命令
redis-benchmark性能测试,Redis 性能测试 | 菜鸟教程 (runoob.com)
测试:redis-benchmark -p 6379 -c 1 -n 100000redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 10000 -q
select n : redis默认16个数据库相互独立,
127.0.0.1:6379> select 2 OK 127.0.0.1:6379[2]> keys * (empty array) 127.0.0.1:6379[2]> set name sam OK 127.0.0.1:6379[2]> get name "sam" 127.0.0.1:6379[2]> keys * 1) "name" 127.0.0.1:6379[2]> select 0 OK 127.0.0.1:6379> keys * 1) "myhash" 2) "key:__rand_int__" 3) "counter:__rand_int__" 4) "name" 5) "mylist" 127.0.0.1:6379> get name "qing"
dbsize:数据库大小
127.0.0.1:6379> keys * 1) "myhash" 2) "key:__rand_int__" 3) "counter:__rand_int__" 4) "name" 5) "mylist" 127.0.0.1:6379> get name "qing" 127.0.0.1:6379> dbsize (integer) 5
flushdb:清除当前数据库
flushall:清除所有数据库
127.0.0.1:6379> keys * 1) "myhash" 2) "key:__rand_int__" 3) "counter:__rand_int__" 4) "name" 5) "mylist" 127.0.0.1:6379> select 3 OK 127.0.0.1:6379[3]> keys * (empty array) 127.0.0.1:6379[3]> set name qing OK 127.0.0.1:6379[3]> set age 18 OK 127.0.0.1:6379[3]> set sex man OK 127.0.0.1:6379[3]> keys * 1) "sex" 2) "name" 3) "age" 127.0.0.1:6379[3]> dbsize (integer) 3 127.0.0.1:6379[3]> flushdb OK 127.0.0.1:6379[3]> keys * (empty array) 127.0.0.1:6379[3]> flushall OK 127.0.0.1:6379[3]> select 0 OK 127.0.0.1:6379> keys * (empty array)
append :在键值对后面添加一个,如果key值不存在就直接set一个key
strlen:表示字符串长度
127.0.0.1:6379> set name qing OK 127.0.0.1:6379> get name "qing" 127.0.0.1:6379> exists name (integer) 1 127.0.0.1:6379> append name ming #在键值后面添加 (integer) 8 127.0.0.1:6379> get name "qingming" 127.0.0.1:6379> strlen name #显示键值的长度 (integer) 8
incr:默认增加1
decr:默认减1
incrby:增加设置步长
decrby:减少设置步长
127.0.0.1:6379> set book 0 OK 127.0.0.1:6379> incr book #增加 (integer) 1 127.0.0.1:6379> incr book (integer) 2 127.0.0.1:6379> incr book (integer) 3 127.0.0.1:6379> get book "3" 127.0.0.1:6379> decr book (integer) 2 127.0.0.1:6379> decr book #减少 (integer) 1 127.0.0.1:6379> get book "1" 127.0.0.1:6379> incrby book 5 #增加步长 (integer) 6 127.0.0.1:6379> get book "6" 127.0.0.1:6379> incrby book 10 (integer) 16 127.0.0.1:6379> get book "16" 127.0.0.1:6379> decrby book 3 #减少步长 (integer) 13
getrange key 起始 结尾:获取范围 如果 (0 -1)返回全部的字符串
setrange key 起始 替换内容:
127.0.0.1:6379> set key qiangfengchufu OK 127.0.0.1:6379> getrange key 1 1 "i" 127.0.0.1:6379> getrange key 1 2 "ia" 127.0.0.1:6379> getrange key 3 4 "ng" 127.0.0.1:6379> setrange key 0 444 (integer) 14 127.0.0.1:6379> get key "444ngfengchufu"
setex: 命令为指定的 key 设置值及其过期时间。如果 key 已经存在, SETEX 命令将会替换旧的值。
127.0.0.1:6379> keys * 1) "key" 2) "name" 3) "age" 127.0.0.1:6379> setex name 30 qqq OK 127.0.0.1:6379> ttl name (integer) 25 127.0.0.1:6379> ttl name (integer) 19 127.0.0.1:6379> get name (nil) 127.0.0.1:6379> keys * 1) "key" 2) "age" 127.0.0.1:6379> set name qing OK 127.0.0.1:6379> setex name 1000 qqq OK 127.0.0.1:6379> get name "qqq" 127.0.0.1:6379> setex p 100 uuu OK 127.0.0.1:6379> keys * 1) "p" 2) "key" 3) "name" 4) "age" 127.0.0.1:6379> get p "uuu"
setnx:命令在指定的 key 不存在时,为 key 设置指定的值。
127.0.0.1:6379> keys * 1) "key" 2) "name" 3) "age" 127.0.0.1:6379> setnx name q (integer) 0 127.0.0.1:6379> get name "qqq" 127.0.0.1:6379> setnx dname q (integer) 1 127.0.0.1:6379> keys * 1) "dname" 2) "key" 3) "name" 4) "age"
mset:批量设置值
mget:批量获取值
127.0.0.1:6379> keys * (empty array) 127.0.0.1:6379> mset name qing age 18 sex man OK 127.0.0.1:6379> keys * 1) "sex" 2) "name" 3) "age" 127.0.0.1:6379> mget name age sex 1) "qing" 2) "18" 3) "man"
msetnx:原子性的操作 ,于所有给定 key 都不存在时,同时设置一个或多个 key-value 对
127.0.0.1:6379> keys * 1) "sex" 2) "name" 3) "age" 127.0.0.1:6379> del age (integer) 1 127.0.0.1:6379> keys * 1) "sex" 2) "name" 127.0.0.1:6379> msetnx age 18 class 1 (integer) 1 127.0.0.1:6379> keys * 1) "class" 2) "sex" 3) "name" 4) "age" 127.0.0.1:6379> msetnx age 11 school dongguan (integer) 0 127.0.0.1:6379> keys * 1) "class" 2) "sex" 3) "name" 4) "age" 127.0.0.1:6379> get age "18" 127.0.0.1:6379>
创建对象:创建对象的时候只用:
127.0.0.1:6379> keys * (empty array) 127.0.0.1:6379> set user:1:name zhangsan OK 127.0.0.1:6379> keys * 1) "user:1:name" 127.0.0.1:6379> mset user:1:age 1 user:1:sex man OK 127.0.0.1:6379> keys * 1) "user:1:sex" 2) "user:1:age" 3) "user:1:name" 127.0.0.1:6379> mget user:1:age user:1:sex user:1:name 1) "1" 2) "man" 3) "zhangsan" 127.0.0.1:6379>
getset:先get然后set命令 如果不存在返回nil,如果存在会设置新值
127.0.0.1:6379> mset name qing age 18 OK 127.0.0.1:6379> getset age 11 "18" 127.0.0.1:6379> get age "11" 127.0.0.1:6379> getset sex man (nil) 127.0.0.1:6379> keys * 1) "sex" 2) "name" 3) "age" 127.0.0.1:6379> get sex "man" 127.0.0.1:6379>
redis中List可以当作栈 队列 阻塞队列,所有list命令以L开头的
lpush :在list放值放在首部,可以一次性存放多个值
lrange:获取范围 (0 ,-1)选取全部的值
127.0.0.1:6379> lpush list value01 (integer) 1 127.0.0.1:6379> lpush list value02 (integer) 2 127.0.0.1:6379> lpush list value03 (integer) 3 127.0.0.1:6379> lpush list01 01value (integer) 1 127.0.0.1:6379> lpush list01 02value (integer) 2 127.0.0.1:6379> keys * 1) "list" 2) "list01" 127.0.0.1:6379> lrange list 0 -1 1) "value03" 2) "value02" 3) "value01"
rpush:在底部放值
lpush:在顶部放置
(看成从从左到右的队列,rpush放在右边,lpush放在左边)
127.0.0.1:6379> rpush list value04 (integer) 4 127.0.0.1:6379> keys * 1) "list" 2) "list01" 127.0.0.1:6379> lrange list 0 -1 1) "value03" 2) "value02" 3) "value01" 4) "value04" 127.0.0.1:6379> lrange list 1 2 1) "value02"
rpop:移除右边第一个元素,返回移除的元素
127.0.0.1:6379> lrange list 0 -1 1) "value03" 2) "value02" 3) "value01" 4) "value04" 127.0.0.1:6379> rpop list "value04" 127.0.0.1:6379> lrange list 0 -1 1) "value03" 2) "value02" 3) "value01"
lpop:移除左边第一个元素,返回移除的元素
127.0.0.1:6379> lrange list 0 -1 1) "value03" 2) "value02" 3) "value01" 127.0.0.1:6379> lpop list "value03" 127.0.0.1:6379> lrange list 0 -1 1) "value02" 2) "value01"
lindex:通过下标获取值
127.0.0.1:6379> lrange list 0 -1 1) "vvalue04" 2) "value03" 3) "value02" 4) "value01" 127.0.0.1:6379> lindex list 4 (nil) 127.0.0.1:6379> lindex list 3 "value01"
llen:返回长度
127.0.0.1:6379> llen list (integer) 4
lrem:移除指定的值 list,中可以有重复的值,如果输入的是0则会删除全部元素
127.0.0.1:6379> lpush car biyadi baoma benchi benchi dazhong baoma (integer) 6 127.0.0.1:6379> lrange car 0 -1 1) "baoma" 2) "dazhong" 3) "benchi" 4) "benchi" 5) "baoma" 6) "biyadi" 127.0.0.1:6379> lrem car 2 baoma (integer) 2 127.0.0.1:6379> lrange car 0 -1 1) "dazhong" 2) "benchi" 3) "benchi" 4) "biyadi"
ltrim:通过下标截取长度
127.0.0.1:6379> lpush car baom benchi biyadi dazhong aodi (integer) 5 127.0.0.1:6379> lrange car 0 -1 1) "aodi" 2) "dazhong" 3) "biyadi" 4) "benchi" 5) "baom" 127.0.0.1:6379> ltrim car 1 3 OK 127.0.0.1:6379> lrange car 0 -1 1) "dazhong" 2) "biyadi" 3) "benchi" 127.0.0.1:6379> ltrim car 0 0 OK 127.0.0.1:6379> lrange car 0 -1 1) "dazhong"
rpoplpush:移除列表最后一个元素,将他移动到新的列表中
127.0.0.1:6379> lpush car1 baoma1 baoma2 baoma 3 (integer) 4 127.0.0.1:6379> lpush park aodi (integer) 1 127.0.0.1:6379> kyes * (error) ERR unknown command `kyes`, with args beginning with: `*`, 127.0.0.1:6379> keys * 1) "park" 2) "car1" 127.0.0.1:6379> rpoplpush car1 park "baoma1" 127.0.0.1:6379> lrange car1 0 -1 1) "3" 2) "baoma" 3) "baoma2" 127.0.0.1:6379> lrange park 0 -1 1) "baoma1" 2) "aodi"
lset:将列表中指定的元素替换另外的值,更新操作,不存在则会报错错
127.0.0.1:6379> lrange park 0 -1 1) "baoma1" 2) "aodi" 127.0.0.1:6379> lset park 0 baoma OK 127.0.0.1:6379> lrange park 0 -1 1) "baoma" 2) "aodi" 127.0.0.1:6379> lset park 2 baoma (error) ERR index out of range 127.0.0.1:6379>
linsert:指定集合中的一个值的前或者后插入一个值
127.0.0.1:6379> lrange park 0 -1 1) "baoma" 2) "aodi" 127.0.0.1:6379> linsert park before 1 qing (integer) -1 127.0.0.1:6379> lrange park 0 -1 1) "baoma" 2) "aodi" 127.0.0.1:6379> linsert park before baoma qing (integer) 3 127.0.0.1:6379> lrange park 0 -1 1) "qing" 2) "baoma" 3) "aodi" 127.0.0.1:6379> linsert park after baoma qing (integer) 4 127.0.0.1:6379> lrange park 0 -1 1) "qing" 2) "baoma" 3) "qing" 4) "aodi"
无序,不重复集合
sadd:设置set值
smembers:获取set值
127.0.0.1:6379> sadd car baoma benchi dazhong (integer) 3 127.0.0.1:6379> smembers car 1) "benchi" 2) "dazhong" 3) "baoma"
sismember:是否存在某个元素 1为存在 0为不存在
127.0.0.1:6379> sismember car benchi (integer) 1 127.0.0.1:6379> sismember car o (integer) 0
scard:获取set集合冲元素的个数
srem:移除元素
127.0.0.1:6379> scard car (integer) 3 127.0.0.1:6379> srem car baoma (integer) 1 127.0.0.1:6379> scard car (integer) 2
srandmember:随机抽取一个元素
spop:删除随机的key
127.0.0.1:6379> smembers car 1) "dazhong" 2) "kaidilake" 3) "aodi" 4) "benchi" 5) "sanling" 127.0.0.1:6379> srandmember car "kaidilake" 127.0.0.1:6379> srandmember car "benchi" 127.0.0.1:6379> srandmember car "dazhong" 127.0.0.1:6379> srandmember car "kaidilake" 127.0.0.1:6379> smembers car 1) "dazhong" 2) "kaidilake" 3) "aodi" 4) "benchi" 5) "sanling" 127.0.0.1:6379> spop car "aodi" 127.0.0.1:6379> spop car "kaidilake" 127.0.0.1:6379> smembers car 1) "dazhong" 2) "benchi" 3) "sanling"
smove:将以恶搞指定的key值,移动到另外一个key中
sdiff :差集
sinter:交集
sunion:并集
127.0.0.1:6379> sadd key1 a b c d (integer) 4 127.0.0.1:6379> sadd key2 c d e f (integer) 4 127.0.0.1:6379> smove key1 key2 a #从k1中移动到k2值 (integer) 1 127.0.0.1:6379> smembers key2 #在k2中多了a 1) "f" 2) "e" 3) "d" 4) "c" 5) "a" 127.0.0.1:6379> sdiff key1 key2 #区key1中的差集 1) "b" 127.0.0.1:6379> sinter key1 key2 #k1和k2中一样的 1) "d" 2) "c" 127.0.0.1:6379> sunion key1 key2 #k1和k2并集 1) "a" 2) "e" 3) "b" 4) "f" 5) "d" 6) "c"
相当于Map集合 相当与key1-(key2-value)
hset:设置值
hget:获取值
hmset批量设置值 hset和hmset无本质的差别,hmset设置多个值而hset也可以
hmget:批量获取值
hgetall:获取全部的值
127.0.0.1:6379> hset animal name dog sex male (integer) 2 127.0.0.1:6379> keys * 1) "animal" 127.0.0.1:6379> hget animal name "dog" 127.0.0.1:6379> hget animal sex mal (error) ERR wrong number of arguments for 'hget' command 127.0.0.1:6379> hget animal sex "male" 127.0.0.1:6379> hgetall animal 1) "name" 2) "dog" 3) "sex" 4) "male" 127.0.0.1:6379> flushdb OK 127.0.0.1:6379> hmset animal name daog sex male OK 127.0.0.1:6379> hmget animal name sex 1) "daog"
hdel:删除
127.0.0.1:6379> hdel animal name (integer) 1 127.0.0.1:6379> hget animal sex "male" 127.0.0.1:6379> hgetall animal 1) "sex" 2) "male"
hlen:返回键值对的个数
127.0.0.1:6379> hlen animal (integer) 1
hexists:判断hash指定字段是否存在,只要一个不存在,就都不存在
127.0.0.1:6379> hexists animal name (integer) 0 127.0.0.1:6379> hexists naimal sex (integer) 0 127.0.0.1:6379> hexists animal sex (integer) 1
hkeys:获取是所有的keys2
hvals:获取value值
127.0.0.1:6379> hset student name zhangsan age 18 sex male (integer) 3 127.0.0.1:6379> hkeys student 1) "name" 2) "age" 3) "sex" 127.0.0.1:6379> hvals student 1) "zhangsan" 2) "18" 3) "male"
hincrby:可以增加也可以减少,如果没有对应的key和value可以自己创建一个
127.0.0.1:6379> hincrby key num -2 (integer) -1 127.0.0.1:6379> hincrby key num -2 (integer) -3 127.0.0.1:6379> hgetall key 1) "num" 2) "-3" 3) "value" 4) "10"
hsetex:如果不存在可以设置值,如果存在设置不了值
127.0.0.1:6379> hset student name qing age 18 (integer) 2 127.0.0.1:6379> hsetex student name zhang (error) ERR unknown command `hsetex`, with args beginning with: `student`, `name`, `zhang`, 127.0.0.1:6379> hsetnx student name zhang (integer) 0 127.0.0.1:6379> hsetnx student value zhang (integer) 1 127.0.0.1:6379> hgetall student 1) "name" 2) "qing" 3) "age" 4) "18" 5) "value" 6) "zhang"
主要使用变更的数据,用户信息的保存,更适合对象的存储,String更适合字符串的存储
再set基础上增加了一个值
使用:存储班级成绩,工资表排序,普通消息,重要消息,排行榜
zadd:添加
zrange:(0,-1)查找全部
127.0.0.1:6379> zadd list 5 five 1 one 3 three 4 four 2 two #添加元素 (integer) 5 127.0.0.1:6379> zrange list 0 -1 #显示范围 1) "one" 2) "two" 3) "three" 4) "four" 5) "five" 127.0.0.1:6379> zrange list 0 -1 withscores #显示元素和键值 1) "one" 2) "1" 3) "two" 4) "2" 5) "three" 6) "3" 7) "four" 8) "4" 9) "five" 10) "5"
zrangebyscore key min max [withscores][limit offset count] 补充:(-inf(负无穷) +inf(正无穷))
127.0.0.1:6379> zrangebyscore list -inf +inf 1) "one" 2) "two" 3) "three" 4) "four" 5) "five" 127.0.0.1:6379> zrangebyscore list 2 3 1) "two" 2) "three" 127.0.0.1:6379> zrangebyscore list 2 3 withscores 1) "two" 2) "2" 3) "three" 4) "3"
zrem:移除有序集合中的元素
zcard:获取有序集合的个数
127.0.0.1:6379> zcard list #查询个数 (integer) 5 127.0.0.1:6379> zrem list two #移除一个元素 (integer) 1 127.0.0.1:6379> zcard list (integer) 4
zrevrange:从大到小排序
127.0.0.1:6379> zrange list 0 -1 withscores 1) "one" 2) "1" 3) "two" 4) "2" 5) "three" 6) "3" 7) "four" 8) "4" 9) "five" 10) "5" 127.0.0.1:6379> zrevrange list 0 -1 1) "five" 2) "four" 3) "three" 4) "two" 5) "one"
zcount:获取区间中的成员数量
127.0.0.1:6379> zcount list 1 4 #因为2被移除了 (integer) 3
命令不分大小写,键值分大小写
127.0.0.1:6379> geopos china:city dongguan hangzhou beijing dalian 1) (nil) 2) (nil) 3) (nil) 4) (nil) 127.0.0.1:6379> geopos China:city dongguan hangzhou beijing dalian 1) 1) "113.76000255346298218" 2) "23.04000066850992567" 2) 1) "120.14000147581100464" 2) "30.2800007575645509" 3) 1) "116.39999896287918091" 2) "39.90000009167092543" 4) 1) "121.61000221967697144" 2) "38.90999884014095045"
城市经纬度查询-国内城市经度纬度在线查询工具 (jsons.cn)
再redis中3.2中就推出了,可以推算地理位置,两地之间的距离,范围内的人,两极无法添加
有效的经度从-180度到180度。
有效的纬度从-85.05112878度到85.05112878度
geoadd: key值 纬度 经度 名称
geopos:获取经纬度,一个坐标值
127.0.0.1:6379> geoadd China:city 113.76 23.04 dongguan #添加城市 (integer) 1 127.0.0.1:6379> geoadd China:city 121.61 38.91 dalian (integer) 1 127.0.0.1:6379> geoadd China:city 116.40 39.90 beijing (integer) 1 127.0.0.1:6379> geoadd China:city 120.14 30.28 hangzhou (integer) 1 127.0.0.1:6379> keys * 1) "China:city" 127.0.0.1:6379> geopos China:city hangzhou #查看城市经纬度 1) 1) "120.14000147581100464" 2) "30.2800007575645509" 127.0.0.1:6379> geopos China:city dalian beijing dongguan 1) 1) "121.61000221967697144" 2) "38.90999884014095045" 2) 1) "116.39999896287918091" 2) "39.90000009167092543" 3) 1) "113.76000255346298218" 2) "23.04000066850992567"
geodist:从经纬度获取直接距离 m 米 km 千米 mi 英里 ft 英尺
127.0.0.1:6379> geodist China:city dongguan dalian #显示距离默认是m "1915331.0660" 127.0.0.1:6379> geodist China:city dongguan hangzhou "1024515.9922" 127.0.0.1:6379> geodist China:city dongguan beijing "1891669.2761" 127.0.0.1:6379> geodist China:city dongguan beijing m "1891669.2761" 127.0.0.1:6379> geodist China:city dongguan beijing km #以千米为单位显示 "1891.6693"
georadius: 以给定的经纬度为中心, 找出某一半径内的元素 withdist:获取直接距离 withcoord 获取经纬度,count 限定个数
127.0.0.1:6379> georadius China:city 113 23 2000 km withdist #以经纬度为113 23为中心,周围2000km 以内的距离 1) 1) "dongguan" 2) "77.9279" 2) 1) "hangzhou" 2) "1076.2076" 3) 1) "beijing" 2) "1906.7845" 4) 1) "dalian" 2) "1948.4875" 127.0.0.1:6379> georadius China:city 113 23 2000 km withdist withcoord #显示经纬度 1) 1) "dongguan" 2) "77.9279" 3) 1) "113.76000255346298218" 2) "23.04000066850992567" 2) 1) "hangzhou" 2) "1076.2076" 3) 1) "120.14000147581100464" 2) "30.2800007575645509" 3) 1) "beijing" 2) "1906.7845" 3) 1) "116.39999896287918091" 2) "39.90000009167092543" 4) 1) "dalian" 2) "1948.4875" 3) 1) "121.61000221967697144" 2) "38.90999884014095045" 127.0.0.1:6379> georadius China:city 113 23 2000 km withdist withcoord count 2 #只允许出现两个 1) 1) "dongguan" 2) "77.9279" 3) 1) "113.76000255346298218" 2) "23.04000066850992567" 2) 1) "hangzhou" 2) "1076.2076" 3) 1) "120.14000147581100464" 2) "30.2800007575645509"
georadiusbymember:给一个城市,和半径。确认城市之间的距离,找出位于指定元素周围的其他元素
127.0.0.1:6379> georadiusbymember China:city beijing 1500 km withdist 1) 1) "hangzhou" 2) "1122.5252" 2) 1) "beijing" 2) "0.0000" 3) 1) "dalian" 2) "461.0231"
geohash:返回经纬度的字符串,字符串越接近越相似
127.0.0.1:6379> geohash China:city beijing #返回北京的经纬度哈希值 1) "wx4fbxxfke0" 127.0.0.1:6379> geohash China:city hangzhou 1) "wtmkmb73bc0"
Geo底层是zset,可以使用zset命令才操作geo
redis 2.8.9更新了hyperloglog数据结构 (一个人访问一个网站多次,但是一个人访问)
优点:占用内存是固定的。Redis中每个键占用的内容都是12KB,理论存储近似接近2^64个值,不管存储的内容是什么
有0.81%错误率,可忽略不计,如果不允许容错需要使用set
pfadd:添加key中元素
pfcount:统计不重复的个数
pfmerge:两个旧键合并成一个新键
127.0.0.1:6379> pfadd key q w e r t #第一个键值添加元素 (integer) 1 127.0.0.1:6379> pfcount key (integer) 5 127.0.0.1:6379> pfadd key q w a s d #继续添加,重复的回直接去除 (integer) 1 127.0.0.1:6379> pfcount key (integer) 8 127.0.0.1:6379> pfadd key1 e z x #一个新键 (integer) 1 127.0.0.1:6379> pfmerge key2 key key1 #两个键混合 OK 127.0.0.1:6379> pfcount key2 #混合之后 重复的被去除 (integer) 10 127.0.0.1:6379> get key2 #拆查询所有键被加密 "HYLL\x01\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00PG\x84Ef\x94Df\x80Bb\x80D<\x80@\xc9\x80I\x7f\x80F\x9f\x84I\x8c\x80D\xbf\x84\b"
位存储
统计用户信息,活跃,不活跃,未登录,打卡,两个状态东可以使用bitmaps
setbit:标记状态 0表示未标记 1表示标记了
getbit:查看是否标记
bitcout:统计所有为1的个数
#周1到周4打卡 1为打卡 0为未打卡 127.0.0.1:6379> setbit key 0 1 (integer) 0 127.0.0.1:6379> setbit key 1 0 (integer) 0 127.0.0.1:6379> setbit key 2 3 #不能存储其他数据 (error) ERR bit is not an integer or out of range 127.0.0.1:6379> setbit key 2 0 (integer) 0 127.0.0.1:6379> setbit key 3 1 (integer) 0 127.0.0.1:6379> getbit key 0 (integer) 1 127.0.0.1:6379> getbit key 3 #获取当前状态 (integer) 1 127.0.0.1:6379> bitcount key #一词多少人打卡 (integer) 2
ACID原则,redis单条命令保存原子性,但事务不原子性
redis中的事务没有隔离,单条命令有原子性,但事务不保证有原子性
每次执行完一次事务之后就要重新开启
multi:开启事务 ,入队的时候并没有直接执行
exec:结束事务
127.0.0.1:6379> multi #开启事务 OK 127.0.0.1:6379(TX)> set k1 1 QUEUED 127.0.0.1:6379(TX)> set k2 2 QUEUED 127.0.0.1:6379(TX)> set k3 3 QUEUED 127.0.0.1:6379(TX)> exec #执行事务 1) OK 2) OK 3) OK 127.0.0.1:6379> keys * 1) "k3" 2) "k2" 3) "k1"
discard:放弃事务,里面设设置会全部取消
127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> set k4 4 QUEUED 127.0.0.1:6379(TX)> set k5 3 QUEUED 127.0.0.1:6379(TX)> discard #放弃事务 OK 127.0.0.1:6379> keys * 1) "k3" 2) "k2" 3) "k1"
异常:
1.编译型异常 命令的使用错误
127.0.0.1:6379(TX)> set k1 1 QUEUED 127.0.0.1:6379(TX)> set k2 1 QUEUED 127.0.0.1:6379(TX)> getset k2 #没货创建k2无法设置k2 (error) ERR wrong number of arguments for 'getset' command 127.0.0.1:6379(TX)> exec (error) EXECABORT Transaction discarded because of previous errors.
2.运行时异常
127.0.0.1:6379(TX)> set k1 1 QUEUED 127.0.0.1:6379(TX)> set k2 q QUEUED 127.0.0.1:6379(TX)> incr k2 #字符串不能自增 QUEUED 127.0.0.1:6379(TX)> exec 1) OK 2) OK 3) (error) ERR value is not an integer or out of range
在多线程的时候
watch:加锁头
unwatch:解锁
悲观锁:
乐观锁:
比如:银行
正常:
127.0.0.1:6379> watch (error) ERR wrong number of arguments for 'watch' command 127.0.0.1:6379> set income 1000 OK 127.0.0.1:6379> set pay 0 OK 127.0.0.1:6379> watch income OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> decrby income 100 QUEUED 127.0.0.1:6379(TX)> incrby pay 100 QUEUED 127.0.0.1:6379(TX)> exec 1) (integer) 900 2) (integer) 100
异常:
127.0.0.1:6379> set income 1000 OK 127.0.0.1:6379> set pay 0 OK 127.0.0.1:6379> watch income OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> decrby income 100 QUEUED 127.0.0.1:6379(TX)> incrby pay 100 QUEUED 127.0.0.1:6379(TX)> exec #在执行之前修改了income的值如下 (nil)
修改了income的值
如果再次修改需要进行解锁,如果没解锁会导致一下结果
127.0.0.1:6379> watch income #再次监控进行 OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> decrby income 100 QUEUED 127.0.0.1:6379(TX)> incrby pay 100 QUEUED 127.0.0.1:6379(TX)> exec #报错 (error) EXECABORT Transaction discarded because of previous errors. #由于以前的错误,已放弃Executor事务 127.0.0.1:6379> unwatch #进行解锁 OK 127.0.0.1:6379> watch income OK 127.0.0.1:6379> multi OK 127.0.0.1:6379(TX)> decrby income 100 QUEUED 127.0.0.1:6379(TX)> incrby pay 100 QUEUED 127.0.0.1:6379(TX)> exec #执行成功 1) (integer) 1100 2) (integer) 100