redis数据类型

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简单的api

  • set key value 存储数据
  • get key 获取数据
  • keys * 查看所有key
  • select 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不存在返回null

    127.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 移除value
  • SRANDMEMBER key 随机获取一个元素
  • SRANDMEMBER key n 随机获n个元素
  • spop set 随机弹出一个元素
  • smove set1 set2 value 将value从set1移动到set2
  • sdiff 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获取所有的key
  • hvals k 获取所有的value
  • hsetnc 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 合并到pf1

    127.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 #如果事务执行失败需要先解锁 再重新监听新的值

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值