Nosql特点:
-
解耦
-
方便拓展(数据之间没有关系很好拓展)
-
大数据量高性能(redis 1秒能写8w次,读取11w次,Nosql的缓存记录及是一种细粒度的缓存,性能会比较高。)
-
数据类型是多样的。灵活的。
redis是什么
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
redis能干嘛
1、 内存存储,持久化(ard,aof)
2、 效率高,用于高速缓存
3、 发布订阅系统
4、 地图信息分析
5、 计时器、计数器
redis 特性
多样化数据类型
持久化
集群
事务
性能测试
官方插件(redis-benchmark)
redis常识
- redis默认有16个数据库 可通过redis.conf 中的
databases
调整。 - redis是单线程的 redis是基于内存操作的。cpu不是redis的性能瓶颈,redis瓶颈是根据机器内存和网络带宽。既然可以使用单线程来实现,就是用单线程了。多线程之间的上下文切换也很浪费资源。redis底层是C语言编写的。官方提供数据。redis支出的QPS为10w+
- 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简单的api
set key value
存储数据get key
获取数据keys *
查看所有keyselect index
切换数据库flushdb
清空当前数据库flushall
清空全部数据库exists key
key是否存在expire key num
设置过期时间,过期后自动清除ttl key
查看过期时间move key dbindex
将key移动到目标数据库成功返回1 key不存在返回0,如果key在目标库存在也会导致移动失败
127.0.0.1:6379> set name zhangsan #存储一组数据
OK
127.0.0.1:6379> get name #获取数据
"zhangsan"
127.0.0.1:6379[1]> keys * #查看所有key
1) "name"
127.0.0.1:6379> select 1 #切换数据库
OK
127.0.0.1:6379[1]> get name #不同数据库是隔离的
(nil)
127.0.0.1:6379[1]> set name lisi # 在1 数据库存入数据
OK
127.0.0.1:6379[1]> get name # 获取数据
"lisi"
127.0.0.1:6379[1]> select 0 #切换到0数据库
OK
127.0.0.1:6379> get name # 获取值
"zhangsan"
127.0.0.1:6379> flushdb # 清空当前数据库
OK
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> get name # 其他数据库不受影响
"lisi"
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> set name 123
OK
127.0.0.1:6379> flushall # 清空全部数据库
OK
127.0.0.1:6379> get name #所有数据都被清空
(nil)
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> get name
(nil)
127.0.0.1:6379[1]> exists name # key是否存在
(integer) 1 #1表示存在
127.0.0.1:6379[1]> exists name2
(integer) 0 #0表示不存在
127.0.0.1:6379[1]> expire name 10 #设置name的超时时间为10秒
(integer) 1
127.0.0.1:6379[1]> ttl name #查看name的超时时间
(integer) 7
127.0.0.1:6379[1]> ttl name # 过期时返回-2如果没有设置超时时间返回-1
(integer) -2
数据类型 String
-
append key value
追加字符串 如果key不存在作用相当于set -
strlen key
获取key对应字符串长度 -
incr key
自增 相等于key++ -
decr key
自减 相等于key– -
incrby key num
自增可设置步长 相等于key+=num -
decrby key num
自减 相等于key-=num -
getrange key start end
截取字符串闭区间[start,end] 如果end=-1表示截取到最后 -
setrange key start value
从start 开始替换value -
setex key num value
存储时设置过期时间单位秒 -
setnx key value
如果key不存在创建key 返回1 如果已存在,创建失败 返回0 -
mset k1 v1 k2 v2 ...
一次存储多个值 -
mget k1 k2 k3 ...
一次获取多个值 -
msetnx k1 v1 k2 v2 ....
原子操作,如果有一个失败就都失败。 -
getset k v
先获取再覆盖。如果key不存在返回null127.0.0.1:6379> set name zhang OK 127.0.0.1:6379> APPEND name san #追加字符串 (integer) 8 127.0.0.1:6379> get name "zhangsan" 127.0.0.1:6379> STRLEN name #获取字符串长度 (integer) 8 127.0.0.1:6379> STRLEN name2 #获取字符串长度不存在就返回0 (integer) 0 127.0.0.1:6379> incr count #设置自增 返回count当前值 (integer) 1 127.0.0.1:6379> incr count (integer) 2 127.0.0.1:6379> incr count (integer) 3 127.0.0.1:6379> get count "3" 127.0.0.1:6379> decr count #设置自减 返回count当前值 (integer) 2 127.0.0.1:6379> incrby count 3 #设置自增并设置增长幅度 返回count当前值 (integer) 5 127.0.0.1:6379> incrby count 3 (integer) 8 127.0.0.1:6379> decrby count 3 #设置自减并设置减少幅度 返回count当前值 (integer) 5 127.0.0.1:6379> decrby count 3 (integer) 2 127.0.0.1:6379> get name "zhangsan" 127.0.0.1:6379> getrange name 0 2 #字符串截取 闭区间 "zha" 127.0.0.1:6379> getrange name 0 -1 #字符串截取 闭区间 -1表示到结尾 "zhangsan" 127.0.0.1:6379> set name zhangsan OK 127.0.0.1:6379> get name "zhangsan" 127.0.0.1:6379> SETRANGE name 3 345 #从索引为3的字符串开始后三位替换为345 (integer) 8 127.0.0.1:6379> get name "zha345an" 127.0.0.1:6379> setex name 10 zhangsan # 存储并设置过期时间 OK 127.0.0.1:6379> get name "zhangsan" 127.0.0.1:6379> ttl name #查看过期时间 (integer) 3 127.0.0.1:6379> ttl name (integer) -2 127.0.0.1:6379> get name (nil) 127.0.0.1:6379> setnx name zhangsan # 如果不存在存储成功 (integer) 1 127.0.0.1:6379> setnx name zhangsan # 如果存在存储失败 (integer) 0 127.0.0.1:6379> mset user:1:name zs user:1:age 13 user:1:sex 1 #批量插入 OK 127.0.0.1:6379> mget user:1:name user:1:age user:1:sex #批量读取 1) "zs" 2) "13" 3) "1" 127.0.0.1:6379> msetnx user:1:name zs user:2:age 13 user:2:sex 1 #原子操作 (integer) 0 127.0.0.1:6379> mget user:1:name user:2:age user:2:sex 1) "zs" 2) (nil) 3) (nil) 127.0.0.1:6379> getset user:1:name ls # 先get旧的值再set新的值 "zs" 127.0.0.1:6379> get user:1:name "ls" 127.0.0.1:6379>
List
-
lpush key v1 k2 v2 ...
将一个或者多个值存入redis 左边插入 -
rpush key v1 k2 v2 ...
将一个或者多个值存入redis 右边插入 -
lrange key start end
查看[start ,end]区间的元素,end=-1表示到尾部 -
lpop key
移除最左边的元素 -
rpop key
移除最右边的元素 -
LINDEX key index
通过下标取值 -
llen key
查看list长度 -
lrem key c ount value
删除 count 个 value -
ltrim key start end
只保留区间值。删除其余的值 -
rpoplpush list1 list2
将list1的第一个值移动到list2 -
lset key index value
更新下标为index的值,如果没有会报错 -
linsert key befor|after v1 v2
将v2插入到v1的前面|后面
127.0.0.1:6379> LPUSH list 1 2 3 4 # 左边插入元素
(integer) 4
127.0.0.1:6379> LRANGE list 0 -1 #查看所有元素
1) "4"
2) "3"
3) "2"
4) "1"
====================================================================
127.0.0.1:6379> rPUSH list a b c d e #右边插入元素
(integer) 9
127.0.0.1:6379> LRANGE list 0 -1 #查看所有元素
1) "4"
2) "3"
3) "2"
4) "1"
5) "a"
6) "b"
7) "c"
8) "d"
9) "e"
====================================================================
127.0.0.1:6379> lpop list # 移除最左边的元素
"4"
====================================================================
127.0.0.1:6379> rpop list #移除最右边的元素
"e"
====================================================================
127.0.0.1:6379> LINDEX list 0 # 查看第一个元素
"3
====================================================================
127.0.0.1:6379> llen list #查看list长度
(integer) 7
====================================================================
127.0.0.1:6379> LPUSH demo a a b a a # 存储数据
(integer) 5
127.0.0.1:6379> LREM demo 3 a # 删除3个a
(integer) 3
127.0.0.1:6379> LRANGE demo 0 -1 # 查看所有
1) "b"
2) "a"
====================================================================
127.0.0.1:6379> LPUSH demo2 a b c d
(integer) 4
127.0.0.1:6379> LTRIM demo2 1 2 #只保留 下标在[1,2]之间的数据
OK
127.0.0.1:6379> LRANGE demo2 0 -1
1) "c"
2) "b"
====================================================================
127.0.0.1:6379> LPUSH list1 a b c
(integer) 3
127.0.0.1:6379> LPUSH list2 1 2 3
(integer) 3
127.0.0.1:6379> RPOPLPUSH list1 list2
"a"
127.0.0.1:6379> LRANGE list1 0 -1
1) "c"
2) "b"
127.0.0.1:6379> LRANGE list2 0 -1
1) "a"
2) "3"
3) "2"
4) "1"
====================================================================
127.0.0.1:6379> LPUSH demo 1 2 3
(integer) 3
127.0.0.1:6379> LSET demo 0 5 # 将0号位置替换为5
OK
127.0.0.1:6379> LSET demo 3 6 # 如果不存在会报错
(error) ERR index out of range
127.0.0.1:6379> LRANGE demo 0 -1
1) "5"
2) "2"
3) "1"
====================================================================
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> LPUSH demo a b c
(integer) 3
127.0.0.1:6379> LINSERT demo before b z #将b不存咋则不会插入并返回失败插入b的前面若b
(integer) 4
127.0.0.1:6379> LRANGE demo 0 -1
1) "c"
2) "z"
3) "b"
4) "a"
set
add key value
向set中添加元素smembers key
查看元素所有值sismember key value
查看value是否存在scard set
获取set长度srem key value
移除valueSRANDMEMBER key
随机获取一个元素SRANDMEMBER key n
随机获n个元素spop set
随机弹出一个元素smove set1 set2 value
将value从set1移动到set2sdiff set1 set2
去set1与set2的差集sinter set1 set2
去set1与set2的交集sunion set1 set2
去set1与set2的并集
127.0.0.1:6379> sadd set 1 2 3 #添加元素
(integer) 3
127.0.0.1:6379> SMEMBERS set #查看所有元素
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> SISMEMBER set 2 # 判断set中是否有2
(integer) 1
127.0.0.1:6379> SCARD set #获取set长度
(integer) 3
127.0.0.1:6379> srem set 1 # 删除 值为1的元素
(integer) 1
127.0.0.1:6379> SMEMBERS set # 查看所有元素
1) "2"
2) "3"
127.0.0.1:6379> SRANDMEMBER set # 随机获取一个元素
"2"
127.0.0.1:6379> SRANDMEMBER set # 随机获取一个元素
"3"
127.0.0.1:6379> SRANDMEMBER set # 随机获取一个元素
"3"
127.0.0.1:6379> SRANDMEMBER set # 随机获取一个元素
"2"
127.0.0.1:6379> SRANDMEMBER set 2 # 随机获取2个元素
1) "2"
2) "3"
127.0.0.1:6379> spop set # 随机弹出一个元素
"2"
127.0.0.1:6379> SMEMBERS set # 查看所有元素
1) "3"
====================================================================
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> sadd set1 1 2 3 4
(integer) 4
127.0.0.1:6379> sadd set2 a b c d
(integer) 4
127.0.0.1:6379> smove set1 set2 1
(integer) 1
127.0.0.1:6379> SMEMBERS set2
1) "b"
2) "d"
3) "a"
4) "c"
5) "1"
====================================================================
127.0.0.1:6379> flushdb #清空数据库
OK
127.0.0.1:6379> SADD set1 a b c d
(integer) 4
127.0.0.1:6379> SADD set2 c d e f
(integer) 4
127.0.0.1:6379> sdiff set1 set2 # 差集
1) "b"
2) "a"
127.0.0.1:6379> sinter set1 set2 # 交集
1) "d"
2) "c"
127.0.0.1:6379> sunion set1 set2 # 并集
1) "b"
2) "d"
3) "a"
4) "e"
5) "f"
6) "c"
127.0.0.1:6379>
Hash
hset k k v k v k v...
存值hget key key
取值hmset k k1 v1 k2 v2 ...
一次存多个hmget k k1 k2 ...
一次取多个hgetall k
取所有的值hdel k k
删除一条数据hlen k
获取长度hkeys k
获取所有的keyhvals k
获取所有的valuehsetnc k k v
不存在才存储
127.0.0.1:6379> flushdb #清空数据库
OK
127.0.0.1:6379> hset user01 name zs age 12 #hset存储多组键值对
(integer) 2
127.0.0.1:6379> hmset user01 address beijing zipcode 000000 #hmset存储多组键值对
OK
127.0.0.1:6379> hget user01 name #通过hget获取一组值
"zs"
127.0.0.1:6379> hget user01 age#通过hget获取一组值
"12"
127.0.0.1:6379> hmget user01 name age#通过hmget获取多组值
1) "zs"
2) "12"
127.0.0.1:6379> hgetall user01 # 获取所有值
1) "name"
2) "zs"
3) "age"
4) "12"
5) "address"
6) "beijing"
7) "zipcode"
8) "000000"
127.0.0.1:6379> hdel user01 zipcode # 删除 zipcode
(integer) 1
127.0.0.1:6379> hgetall user01
1) "name"
2) "zs"
3) "age"
4) "12"
5) "address"
6) "beijing"
127.0.0.1:6379> hlen user01 # 获取长度
(integer) 3
127.0.0.1:6379> hkeys user01 #查看所有的key
1) "name"
2) "age"
3) "address"
127.0.0.1:6379> HVALS user01 # 查看所有的value
1) "zs"
2) "12"
3) "beijing"
127.0.0.1:6379> hsetnx user01 zipcode 000000 #如果不存在就写入数据
(integer) 1
127.0.0.1:6379> hsetnx user01 zipcode 000000 #如果存在就不写入数据
(integer) 0
zset(有序集合)
-
zadd key score value score value … 存储并设置权重
-
zrange start end 查看区间值
-
zrangebyscore key min max 排序并指定最大值和最小值 (-inf,+inf 表示负无穷到正无穷)
-
zrangebyscore key min max withscores 排序并显示分数
-
zrem key value 删除数据
-
zcard key 显示长度
-
zrevrange key start end 倒叙排序
-
zcount key min max 获取指定区间成员数量
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> zadd set1 10 zs 5 li 100 ww #添加数据
(integer) 3
127.0.0.1:6379> ZRANGE set1 0 -1 #查看数据默认就是按score排序
1) "li"
2) "zs"
3) "ww"
127.0.0.1:6379> ZRANGEBYSCORE set1 5 50 #按照score排序并指定范围
1) "li"
2) "zs"
127.0.0.1:6379> ZRANGEBYSCORE set1 5 50 withscores#按照score排序并指定范围 并显示分数
1) "li"
2) "5"
3) "zs"
4) "10"
127.0.0.1:6379> zcard set1 # 查看元素个数
(integer) 3
127.0.0.1:6379> ZREM set1 #ww #删除ww
(integer) 1
127.0.0.1:6379> zcard set1 #查看元素个数
(integer) 2
127.0.0.1:6379> ZREVRANGE set1 0 -1 withscores #倒叙排序
1) "zs"
2) "10"
3) "li"
4) "5"
127.0.0.1:6379> zadd set2 1 aa 2 bb 3 cc 4 dd
(integer) 4
127.0.0.1:6379> ZRANGE set2 0 -1
1) "aa"
2) "bb"
3) "cc"
4) "dd"
127.0.0.1:6379> ZCOUNT set2 2 5 # 统计区间范围内的元素个数
(integer) 3
geospatital (地理位置)
-
geoadd key 维度 经度 name
将指定的地理空间位置(纬度、经度、名称)添加到指定的
key
中。这些数据将会存储到sorted set
这样的目的是为了方便使用GEORADIUS或者GEORADIUSBYMEMBER命令对数据进行半径查询等操作。该命令以采用标准格式的参数x,y,所以经度必须在纬度之前。这些坐标的限制是可以被编入索引的,区域面积可以很接近极点但是不能索引。具体的限制,由EPSG:900913 / EPSG:3785 / OSGEO:41001 规定如下:
- 有效的经度从-180度到180度。
- 有效的纬度从-85.05112878度到85.05112878度。
当坐标位置超出上述指定范围时,该命令将会返回一个错误
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> GEOADD city 116.23128 40.22077 "beijing" 121.48941 31.40527 "shanghai"
(integer) 2
127.0.0.1:6379> GEOADD city 113.27324 23.15792 guangzhou 113.6401 34.72468 zhengzhou 116.29845 39.95933 haidian
(integer) 3
127.0.0.1:6379>
-
geodist 返回两个给定位置之间的距离
如果两个位置之间的其中一个不存在, 那么命令返回空值。
指定单位的参数 unit 必须是以下单位的其中一个:
- m 表示单位为米。
- km 表示单位为千米。
- mi 表示单位为英里。
- ft 表示单位为英尺。
如果用户没有显式地指定单位参数, 那么
GEODIST
默认使用米作为单位。GEODIST
命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差。127.0.0.1:6379> GEODIST city beijing zhengzhou km # 查看北京到郑州的距离。根据预先存储的经纬度进行计算 三位设置为km "652.6135" 127.0.0.1:6379> GEODIST city beijing xiamen km #之前没有存储厦门的经纬度所以无法计算,返回空 (nil)
-
geohash
返回一个或多个位置元素的 Geohash 表示。
127.0.0.1:6379> GEOHASH city beijing shanghai 1) "wx4sucvncn0" 2) "wtw6st1uuq0" 127.0.0.1:6379>
-
geopos
从
key
里返回所有给定位置元素的位置(经度和纬度)。127.0.0.1:6379> GEOPOS city beijing 1) 1) "116.23128265142440796" 2) "40.22076905438526495" 127.0.0.1:6379> GEOPOS city beijing shanghai 1) 1) "116.23128265142440796" 2) "40.22076905438526495" 2) 1) "121.48941010236740112" 2) "31.40526993848380499" 127.0.0.1:6379>
-
georadius
格式:
georadius 经度 维度 半径 单位
以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
范围可以使用以下其中一个单位:
- m 表示单位为米。
- km 表示单位为千米。
- mi 表示单位为英里。
- ft 表示单位为英尺。
在给定以下可选项时, 命令会返回额外的信息:
WITHDIST
: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。WITHCOORD
: 将位置元素的经度和维度也一并返回。WITHHASH
: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
命令默认返回未排序的位置元素。 通过以下两个参数, 用户可以指定被返回位置元素的排序方式:
ASC
: 根据中心的位置, 按照从近到远的方式返回位置元素。DESC
: 根据中心的位置, 按照从远到近的方式返回位置元素。
在默认情况下, GEORADIUS 命令会返回所有匹配的位置元素。 虽然用户可以使用 COUNT
<count>
选项去获取前 N 个匹配元素, 但是因为命令在内部可能会需要对所有被匹配的元素进行处理, 所以在对一个非常大的区域进行搜索时, 即使只使用COUNT
选项去获取少量元素, 命令的执行速度也可能会非常慢。 但是从另一方面来说, 使用COUNT
选项去减少需要返回的元素数量, 对于减少带宽来说仍然是非常有用的。127.0.0.1:6379> GEORADIUS city 116 40 100 km # 查看经纬为116 维度为40 的坐标 在100公里范围内的城市 1) "haidian" 2) "beijing" 127.0.0.1:6379> GEORADIUS city 116 40 100 km WITHCOORD # 查看范围内的城市并返回城市的位置 1) 1) "haidian" 2) 1) "116.2984505295753479" 2) "39.95933030984756584" 2) 1) "beijing" 2) 1) "116.23128265142440796" 2) "40.22076905438526495" 127.0.0.1:6379> GEORADIUS city 116 40 100 km WITHDIST # 查看范围内的城市并返回和城市的距离 1) 1) "haidian" 2) "25.8359" 2) 1) "beijing" 2) "31.4650" 127.0.0.1:6379> GEORADIUS city 116 40 100 km WITHDIST count 1 # 查看范围内的城市并返回和城市的距离 并界定返回个数 count不会减少查询和计算效率 1) 1) "haidian" 2) "25.8359" 127.0.0.1:6379> GEORADIUS city 116 40 100 km WITHDIST desc #按照距离远近进行排序 并指定排序规则为倒序 1) 1) "beijing" 2) "31.4650" 2) 1) "haidian" 2) "25.8359" 127.0.0.1:6379> GEORADIUS city 116 40 100 km WITHDIST asc #按照距离远近进行排序 并指定排序规则为正序 1) 1) "haidian" 2) "25.8359" 2) 1) "beijing" 2) "31.4650" 127.0.0.1:6379>
-
georadiusbymember
指定成员的位置被用作查询的中心 ,找出范围内的元素
127.0.0.1:6379> GEORADIUSBYMEMBER city beijing 100 km 1) "haidian" 2) "beijing" 127.0.0.1:6379> GEORADIUSBYMEMBER city beijing 1000 km 1) "zhengzhou" 2) "haidian" 3) "beijing"
hyperloglog 基数统计
基数:不重复的元素
优点:占用的内存是固定的。2^64不同的元素的基数只需要12kb的内存
应用:统计网站的uv(网站独立访客)
-
pdadd k v1 v2 v3
添加数据 -
pfcount key
查看基数数量 -
pfmerge pf1 pf2 pf3 ...
将pf2 pf3 合并到pf1127.0.0.1:6379> PFADD demo1 a b c #创建一个集合 (integer) 1 127.0.0.1:6379> PFADD demo2 b c c d #创建一个集合 (integer) 1 127.0.0.1:6379> PFCOUNT demo1 demo2 #查看两个集合的基数个数 (integer) 4 127.0.0.1:6379> PFCOUNT demo1 # 查看 demo1的基数个数 (integer) 3 127.0.0.1:6379> PFCOUNT demo2 # 查看 demo2的基数个数 (integer) 3 127.0.0.1:6379> PFMERGE demo3 demo1 demo2 # 将demo2 demo1 合并成demo3 OK 127.0.0.1:6379> PFCOUNT demo2 #查看 demo2的基数个数 (integer) 3 127.0.0.1:6379> PFCOUNT demo3 #查看 demo3的基数个数 (integer) 4 127.0.0.1:6379>
bitmaps
- 优点:
基于最小单位存储。只能存储0|1 节省空间
设置时候时间复杂度O(1)、读取时候时间复杂度O(n),操作是非常快的
- 缺点
redis中bit映射被限制在512MB之内,所以最大是2^32位。建议每个key的位数都控制下,因为读取时候时间复杂度O(n),越大的串读的时间花销越多
-
setbit key index 0|1
存储 -
getbit key index
读取 -
bitcount key
统计 -
bit key startindex endindex
区间统计
redis的事务
- redis事务的本质是一组命令的集合 一个事物中的所有命令都会被序列化,在事务的执行过程中,会按照顺序执行。
- redis的事务没有隔离级别的的概念
- 所有命令在事务中并没有被执行只有发起执行命令才会被执行
- redis的单条命令保证原子性。但是事务不保证原子性
- 编译型异常(语法错误) 事务所有命令都不会被执行
- 运行时异常(执行时出现的错误) 单条命令的错误不会影响其他命令的执行
multi
开启事务- …sql命令
exec
提交事务discard
放弃事务(回滚)
127.0.0.1:6379> flushdb # 清空数据库
OK
127.0.0.1:6379> MULTI #开启事务
OK
127.0.0.1:6379> set user:01:name zs # 在事务中录入命令 此时命令被未被执行其他客户端也无法获取事务中的数据
QUEUED
127.0.0.1:6379> set user:01:age lisi # 在事务中录入命令 同上
QUEUED
127.0.0.1:6379> mget user:01:name user:01:age # 在事务中录入命令 同上
QUEUED
127.0.0.1:6379> exec # 执行事务中的命令
1) OK
2) OK
3) 1) "zs"
2) "lisi"
##################################################################
127.0.0.1:6379> MULTI # 开启事务
OK
127.0.0.1:6379> setnx name zs # 存值
QUEUED
127.0.0.1:6379> setnx name lisi # 存值
QUEUED
127.0.0.1:6379> EXEC 执行
1) (integer) 1 #第一条命令执行成功
2) (integer) 0 #第二条命令执行失败
127.0.0.1:6379> get name # 没有原子性。第二条失败不影响第一条
"zs"
##################################################################
127.0.0.1:6379> MULTI # 开启事务
OK
127.0.0.1:6379> set name zs
QUEUED
127.0.0.1:6379> aaa #非法命令 事务不是被执行。
(error) ERR unknown command `aaa`, with args beginning with:
127.0.0.1:6379> EXEC 因为含有非法命令事务会直接失败
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379>
============================================================
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set user:02:name zs
QUEUED
127.0.0.1:6379> DISCARD # 放弃事务
OK
127.0.0.1:6379> get user:02:name # 命令不会被执行
(nil)
127.0.0.1:6379>
watch 监听
- 和事务一起用。记录key 如果这个key在在一个事务提交之前发生了变化。会导致事务执行失败。
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> set money 1000
OK
127.0.0.1:6379> watch money #监听money
OK
127.0.0.1:6379> MULTI #开启事务
OK
127.0.0.1:6379> DECRBY money 100 #修改money的值
QUEUED
127.0.0.1:6379> EXEC #执行命令
1) (integer) 900
127.0.0.1:6379> get money #修改成功
"900"
127.0.0.1:6379>
###############################################################################
127.0.0.1:6379> get money
"900"
127.0.0.1:6379> watch money #监听money
OK
127.0.0.1:6379> MULTI #开启事务
OK
127.0.0.1:6379> DECRBY money 100
QUEUED
#【此时另开一个客户端执行 DECRBY money 300】
127.0.0.1:6379> EXEC #事务执行失败
(nil)
127.0.0.1:6379> get money # 值没有改变【事务中的命令没有生效】
"600"
127.0.0.1:6379> UNWATCH #如果事务执行失败需要先解锁 再重新监听新的值