安装

安装:https://www.cnblogs.com/hunanzp/p/12304622.html
VSCode 链接虚拟机:https://www.cnblogs.com/hi3254014978/p/12681594.html
image.png
image.png

基本操作

  1. 127.0.0.1:6379> select 0 # 选择0号数据库,可以从0-15
  2. OK
  3. 127.0.0.1:6379> keys * # 该数据库的所有key
  4. (empty array)
  5. 127.0.0.1:6379> set name zs # name = zs
  6. OK
  7. 127.0.0.1:6379> keys *
  8. 1) "name"
  9. 127.0.0.1:6379> flushall # 清空所有的数据库
  10. OK
  11. 127.0.0.1:6379> set name zms
  12. OK
  13. 127.0.0.1:6379> keys *
  14. 1) "name"
  15. 127.0.0.1:6379> get name #获取名字
  16. "zms"
  17. 127.0.0.1:6379> EXISTS nam # 是否存在一个key,0代表不存在
  18. (integer) 0
  19. 127.0.0.1:6379> EXISTS name # 1代表存在
  20. (integer) 1
  21. 127.0.0.1:6379> move name
  22. (error) ERR wrong number of arguments for 'move' command
  23. 127.0.0.1:6379> move name 1 #移除key
  24. (integer) 1
  25. 127.0.0.1:6379> keys *
  26. (empty array)
  27. 127.0.0.1:6379> set name zms
  28. OK
  29. 127.0.0.1:6379> expire name 10 #设置过期时间,10s
  30. (integer) 1
  31. 127.0.0.1:6379> ttl name
  32. (integer) 8
  33. 127.0.0.1:6379> ttl name # 剩余的生命周期
  34. (integer) 7
  35. 127.0.0.1:6379> ttl name
  36. (integer) 6
  37. 127.0.0.1:6379> ttl name
  38. (integer) 6
  39. 127.0.0.1:6379> ttl name
  40. (integer) 4
  41. 127.0.0.1:6379> keys *
  42. 1) "name"
  43. 127.0.0.1:6379> keys *
  44. (empty array)
  45. 127.0.0.1:6379> set name zms
  46. OK
  47. 127.0.0.1:6379> type name #查看key的类型
  48. string

类型

String

  1. 127.0.0.1:6379> get name
  2. "zms"
  3. 127.0.0.1:6379> APPEND name "XY" # 添加值,如果key不存在相当于新建
  4. (integer) 5
  5. 127.0.0.1:6379> get name
  6. "zmsXY"
  7. 127.0.0.1:6379> SUBSTR name 1 2 # name[1:2]的子串
  8. "ms"
  9. 127.0.0.1:6379>

自增操作:

  1. 127.0.0.1:6379> set name 0
  2. OK
  3. 127.0.0.1:6379> incr name
  4. (integer) 1
  5. 127.0.0.1:6379> incr name # 自增1
  6. (integer) 2
  7. 127.0.0.1:6379>
  8. 127.0.0.1:6379> set name 0
  9. OK
  10. 127.0.0.1:6379> incr name
  11. (integer) 1
  12. 127.0.0.1:6379> incr name
  13. (integer) 2
  14. 127.0.0.1:6379> decr name # --1
  15. (integer) 1
  16. 127.0.0.1:6379> decr name
  17. 127.0.0.1:6379>
  18. 127.0.0.1:6379> set name 0
  19. OK
  20. 127.0.0.1:6379> INCRBY name 10 #设定步长
  21. (integer) 10

字符串范围

  1. 127.0.0.1:6379> set name hello,World
  2. OK
  3. 127.0.0.1:6379> GETRANGE name 0 2 #name[0:2]
  4. "hel"
  5. 127.0.0.1:6379> GETRANGE name 0 -1 #-1代表整个串
  6. "hello,World"
  7. 127.0.0.1:6379> SETRANGE name 1 xx # index=1开始替换子串
  8. (integer) 11

存在或不存在情况的设置值

  1. 127.0.0.1:6379> SETEX name 10 hello # 设置name的过期时间10s
  2. OK
  3. 127.0.0.1:6379> ttl name
  4. (integer) 8
  5. 127.0.0.1:6379> ttl name
  6. (integer) 7
  7. 127.0.0.1:6379> SETNX mykey redis #不存在则设置值;;;;;分布式锁常用
  8. (integer) 1
  9. 127.0.0.1:6379> get mykey
  10. "redis"
  11. 127.0.0.1:6379> setnx mykey zms #不存在则设置,存在就不设置了
  12. (integer) 0 #返回0,设置失败
  13. 127.0.0.1:6379> get mykey
  14. "redis"

批量set、get

  1. 127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 一次性设置多个key
  2. OK
  3. 127.0.0.1:6379> mget k1 k2 k3 # 一次性获取多个key
  4. 1) "v1"
  5. 2) "v2"
  6. 3) "v3"
  7. 127.0.0.1:6379> msetnx k1 v1 k5 v5 # 这个操作是原子性的,要么多个key一起成功,要么一起失败
  8. (integer) 0
  9. 127.0.0.1:6379> get k5 # 获取失败
  10. (nil)

设置对象

  1. 127.0.0.1:6379> set user:1 {name:zms,age:3} #id为1的user
  2. OK
  3. 127.0.0.1:6379> get user:1
  4. "{name:zms,age:3}"
  5. 127.0.0.1:6379> mset user:1:name xy user:1:age 23 #user:{id}:{field}
  6. OK
  7. 127.0.0.1:6379> get user:1
  8. "{name:zms,age:3}"
  9. 127.0.0.1:6379> mget user:1:name user:1:age
  10. 1) "xy"
  11. 2) "23"

先得到get再设置set

  1. 127.0.0.1:6379> getset name zs # 原本没有name,获取不到,然后设置name=zs
  2. (nil)
  3. 127.0.0.1:6379> get name
  4. "zs"
  5. 127.0.0.1:6379> getset name wu
  6. "zs"
  7. 127.0.0.1:6379> get name
  8. "wu"

使用场景

value除了字符串还可以作为数字

  • 计数器
  • 统计多单位的数量
  • 粉丝数
  • 对象缓存存储

List

  • 可以用来实现队列、栈
  • 所有的list命令都是用’L’、’R’开头的
    1. 127.0.0.1:6379> LPUSH l1 one #将one加入l1的列表 ,在最左边加入
    2. (integer) 1
    3. 127.0.0.1:6379> LPUSH l1 two
    4. (integer) 2
    5. 127.0.0.1:6379> LPUSH l1 three
    6. (integer) 3
    7. 127.0.0.1:6379> lrange l1 0 -1 #获取l1的全部元素
    8. 1) "three" # 按栈的结构来的
    9. 2) "two"
    10. 3) "one"
    11. 127.0.0.1:6379> lrange l1 0 1 # 获取range
    12. 1) "three"
    13. 2) "two"
    14. 127.0.0.1:6379> rpush l1 go #在右边加入列表
    15. (integer) 4
    16. 127.0.0.1:6379> lrange l1 0 -1
    17. 1) "three"
    18. 2) "two"
    19. 3) "one"
    20. 4) "go"
    删除元素
    1. 127.0.0.1:6379> lpush l1 1 #左边加入
    2. (integer) 1
    3. 127.0.0.1:6379> lpush l1 2
    4. (integer) 2
    5. 127.0.0.1:6379> lpush l1 3
    6. (integer) 3
    7. 127.0.0.1:6379> rpush l1 4 # 3 2 1 4 # 右边加入
    8. (integer) 4
    9. 127.0.0.1:6379> lpop l1 # 删除左边的元素
    10. "3"
    11. 127.0.0.1:6379> rpop l1 # 删除右边的元素
    12. "4"
    按索引访问
    1. 127.0.0.1:6379> lrange l1 0 -1
    2. 1) "2"
    3. 2) "1" # 2 1
    4. 127.0.0.1:6379> lindex l1 1 # 获取左边下边为1的值,没有rindex
    5. "1"
    返回长度
    1. 127.0.0.1:6379> lrange l2 0 -1
    2. 1) "three"
    3. 2) "two"
    4. 3) "one"
    5. 127.0.0.1:6379> Llen l2 # 获取长度 Listlen
    6. (integer) 3
    移除指定值,类似取消关注
    lremimage.png ```bash 127.0.0.1:6379> lrange l2 0 -1
    1) “one” 2) “three” 3) “two” 4) “one” 127.0.0.1:6379> lrem l2 1 one # 删除1个one元素,精确匹配 (integer) 1 127.0.0.1:6379> lrange l2 0 -1 1) “three” 2) “two” 3) “one”

127.0.0.1:6379> lrange l2 0 -1 1) “three” 2) “two” 3) “one” 4) “three” 127.0.0.1:6379> lrem l2 2 three # 删除2个three (integer) 2 127.0.0.1:6379> lrange l2 0 -1
1) “two” 2) “one”

  1. 修剪trim,截断
  2. ```bash
  3. 127.0.0.1:6379> lrange l3 0 -1
  4. 1) "two"
  5. 2) "one"
  6. 3) "three"
  7. 4) "four" # two one three four
  8. 127.0.0.1:6379> ltrim l3 1 2 # 只保留[1:2]的元素
  9. OK
  10. 127.0.0.1:6379> lrange l3 0 -1
  11. 1) "one"
  12. 2) "three"

从本列表删除并将其移动到新的列表中

  1. 127.0.0.1:6379> lrange l3 0 -1
  2. 1) "one"
  3. 2) "three"
  4. 127.0.0.1:6379> rpoplpush l3 l4 # 删除l3的最后一个元素并加入到l4中
  5. "three"
  6. 127.0.0.1:6379> lrange l3 0 -1
  7. 1) "one"
  8. 127.0.0.1:6379> lrange l4 0 -1
  9. 1) "three"

更新操作

  1. 127.0.0.1:6379> EXISTS list #不存在
  2. (integer) 0
  3. 127.0.0.1:6379> lset list 0 item # 不存在则无法更新
  4. (error) ERR no such key
  5. 127.0.0.1:6379> lpush list index0
  6. (integer) 1
  7. 127.0.0.1:6379> lrange list 0 -1
  8. 1) "index0"
  9. 127.0.0.1:6379> lset list 0 newintem # 更新index=0位置的值
  10. OK
  11. 127.0.0.1:6379> lrange list 0 -1
  12. 1) "newintem"

在特定元素之前之后插入

  1. 127.0.0.1:6379> rpush list hello
  2. (integer) 1
  3. 127.0.0.1:6379> rpush list world
  4. (integer) 2
  5. 127.0.0.1:6379> linsert list after hello XY # 在hello后面插入xy
  6. (integer) 3
  7. 127.0.0.1:6379> lrange list 0 -1
  8. 1) "hello"
  9. 2) "XY"
  10. 3) "world"
  11. 127.0.0.1:6379> linsert list before hello ZMS # 在hello前面插入zms
  12. (integer) 4
  13. 127.0.0.1:6379> lrange list 0 -1
  14. 1) "ZMS"
  15. 2) "hello"
  16. 3) "XY"
  17. 4) "world"

Set

添加、判断、长度、移除

  1. 127.0.0.1:6379> sadd myset hello
  2. (integer) 1
  3. 127.0.0.1:6379> sadd myset go
  4. (integer) 1
  5. 127.0.0.1:6379> sadd myset go
  6. (integer) 0
  7. 127.0.0.1:6379> smembers myset # 显示所有成员
  8. 1) "hello"
  9. 2) "go"
  10. 127.0.0.1:6379> sismember myset go # go是不是myset的元素
  11. (integer) 1
  12. 127.0.0.1:6379> scard myset # 长度
  13. (integer) 2

移除

  1. 127.0.0.1:6379> SMEMBERS myset
  2. 1) "hello"
  3. 2) "go"
  4. 127.0.0.1:6379> srem myset hello
  5. (integer) 1

随机抽取一个,可以做抽奖

  1. 127.0.0.1:6379> SRANDMEMBER myset
  2. "4"
  3. 127.0.0.1:6379> SRANDMEMBER myset
  4. "1"

随机删除一个

  1. 127.0.0.1:6379> spop myset
  2. "4"
  3. 127.0.0.1:6379> spop myset
  4. "5"
  5. 127.0.0.1:6379> scard myset
  6. (integer) 4

交集 并 差集

  1. 127.0.0.1:6379> sadd s1 1
  2. (integer) 1
  3. 127.0.0.1:6379> sadd s1 2
  4. (integer) 1
  5. 127.0.0.1:6379> sadd s1 3
  6. (integer) 1
  7. 127.0.0.1:6379> sadd s2 3
  8. (integer) 1
  9. 127.0.0.1:6379> sadd s2 4
  10. (integer) 1
  11. 127.0.0.1:6379> sadd s2 5
  12. (integer) 1
  13. 127.0.0.1:6379> SINTER s1 s2 # 交集
  14. 1) "3"
  15. 127.0.0.1:6379> sdiff s1 s2 # 差集
  16. 1) "1"
  17. 2) "2"
  18. 127.0.0.1:6379> SUNION s1 s2 # 并集
  19. 1) "1"
  20. 2) "2"
  21. 3) "3"
  22. 4) "4"
  23. 5) "5"

取出并放入

  1. 127.0.0.1:6379> SMOVE s1 s2 1 # 从s1移除出1放入s2
  2. (integer) 1
  3. 127.0.0.1:6379> SMEMBERS s2 # s2的所有元素
  4. 1) "1"
  5. 2) "3"
  6. 3) "4"
  7. 4) "5"
  8. 127.0.0.1:6379> SMEMBERS s1 # s1的所有元素
  9. 1) "2"
  10. 2) "3"

hash

hash适合存储对象

Related commands

  1. 127.0.0.1:6379> hset h1 name zms # 给H1的hash设置name=zms键值对
  2. (integer) 1
  3. 127.0.0.1:6379> hget h1 name # 读取
  4. "zms"
  5. 127.0.0.1:6379> hmset h1 name vms age 20 par xy # 一次设置多个
  6. OK
  7. 127.0.0.1:6379> hgetall h1 # 获取h1存储的所有的
  8. 1) "name"
  9. 2) "vms"
  10. 3) "age"
  11. 4) "20"
  12. 5) "par"
  13. 6) "xy"
  14. 127.0.0.1:6379> HEXISTS h1 name # h1是否存在name属性
  15. (integer) 1
  16. 127.0.0.1:6379> HEXISTS h1 name
  17. (integer) 1
  18. 127.0.0.1:6379> HEXISTS h1 nam
  19. (integer) 0
  20. 127.0.0.1:6379> HINCRBY h1 name 1 # 给h1的name属性的值+1
  21. (error) ERR hash value is not an integer
  22. 127.0.0.1:6379> HINCRBY h1 age 1
  23. (integer) 21
  24. 127.0.0.1:6379> HINCRBY h1 age -1
  25. (integer) 20
  26. 127.0.0.1:6379> hlen h1 # h1元素的长度
  27. (integer) 3
  28. 127.0.0.1:6379> hkeys h1 # 所有的key
  29. 1) "name"
  30. 2) "age"
  31. 3) "par"
  32. 127.0.0.1:6379> HVALS h1 #所有的val
  33. 1) "vms"
  34. 2) "20"
  35. 3) "xy"
  36. 127.0.0.1:6379> hsetnx h1 name zs # 如果不存在则设置值
  37. (integer) 0
  38. 127.0.0.1:6379> hget h1 name # 获取值
  39. "vms"
  40. 127.0.0.1:6379> hsetnx h1 na zs #不存在则设置
  41. (integer) 1
  42. 127.0.0.1:6379> hget h1 na
  43. "zs"
  44. 127.0.0.1:6379> hstrlen h1 na # 获取na对应的val的长度
  45. (integer) 2
  46. 127.0.0.1:6379> hstrlen h1 name
  47. (integer) 3

ZSet

  1. 127.0.0.1:6379> zadd z1 1 zms # 给z1加入一个元素,zms的分值是1
  2. (integer) 1
  3. 127.0.0.1:6379> zadd z1 2 vms
  4. (integer) 1
  5. 127.0.0.1:6379> zadd z1 3 xy 4 py # 一次加入多个
  6. (integer) 2
  7. 127.0.0.1:6379> zcard z1 # 数量
  8. (integer) 4
  9. 127.0.0.1:6379> zcount z1 1 3 # z1中分数在[1,3]的数量
  10. (integer) 3
  11. 127.0.0.1:6379> zincrby z1 1 zms # 给zms对应的score+1
  12. "2"
  13. 127.0.0.1:6379> zcount z1 1 2 #[1,2]的数量
  14. (integer) 2
  15. 127.0.0.1:6379> zrange z1 0 -1 # 不带分数的查询所有
  16. 1) "vms"
  17. 2) "zms"
  18. 3) "xy"
  19. 4) "py"
  20. 127.0.0.1:6379> zrange z1 0 -1 withscores # 查询所有,同时显示分数
  21. 1) "vms"
  22. 2) "2"
  23. 3) "zms"
  24. 4) "2"
  25. 5) "xy"
  26. 6) "3"
  27. 7) "py"
  28. 8) "4"
  29. 127.0.0.1:6379> ZRANGEBYSCORE z1 0 3 # [0,3]分数的
  30. 1) "vms"
  31. 2) "zms"
  32. 3) "xy"
  33. 127.0.0.1:6379> ZRANGEBYSCORE z1 -inf +inf # 负无穷到正无穷分数的
  34. 1) "vms"
  35. 2) "zms"
  36. 3) "xy"
  37. 4) "py"
  38. 127.0.0.1:6379> ZRANGEBYSCORE z1 -inf 2 #3 分数<2的
  39. 1) "vms"
  40. 2) "zms"
  41. 127.0.0.1:6379> zrem z1 zms # 从z1中删除zms
  42. (integer) 1
  43. 127.0.0.1:6379> ZREVRANGE z1 1 2
  44. 1) "xy"
  45. 2) "vms"
  46. 127.0.0.1:6379> ZREVRANGE z1 2 1
  47. (empty array)
  48. 127.0.0.1:6379> zscore z1 vms # 获取元素对应到score
  49. "2"

应用场景:
热榜之类的

GEO

https://redis.io/commands/geoadd
https://www.runoob.com/redis/redis-geo.html
https://api.map.baidu.com/lbsapi/getpoint/index.html
底层实现是zset,所以可以使用zset的命令

  1. ## GEOADD key longitude latitude member [longitude latitude member ...]
  2. ## GeoADD key 经 纬度 成员名称 可以添加多个
  3. 127.0.0.1:6379> GEOADD china:city 116.3 39.9 beijing 121.4 31.2 shanghai 108.9 34.3 xian
  4. (integer) 3
  5. 127.0.0.1:6379> geoadd china:city 106 29 chongqing 114.4 37.1 xingtai 120.6 31.1 suzhou
  6. (integer) 3
  7. 127.0.0.1:6379> geopos china:city xian # 获取元素的位置
  8. 1) 1) "108.90000075101852417"
  9. 2) "34.30000007880482116"
  10. 127.0.0.1:6379> geopos china:city xingtai
  11. 1) 1) "114.39999908208847046"
  12. 2) "37.10000008523787329"
  13. ## GEODIST key member1 member2 [m|km|ft|mi]
  14. 127.0.0.1:6379> GEODIST china:city xian chongqing km # 获取距离
  15. "650.2195"
  16. 127.0.0.1:6379> GEODIST china:city suzhou chongqing km
  17. "1423.8065"
  18. 127.0.0.1:6379> GEODIST china:city shzhou shanghai
  19. (nil)
  20. 127.0.0.1:6379> GEODIST china:city shzhou shanghai km
  21. (nil)
  22. 127.0.0.1:6379> GEODIST china:city shzhou shanghai km
  23. (nil)
  24. 127.0.0.1:6379> zrange china:city 0 -1 # 获取所有的元素
  25. 1) "chongqing"
  26. 2) "xian"
  27. 3) "suzhou"
  28. 4) "shanghai"
  29. 5) "xingtai"
  30. 6) "beijing"
  31. 127.0.0.1:6379> GEODIST china:city suzhou shanghai km
  32. "76.9593"
  33. ## 以给定坐标为中心,给定距离半径内的城市
  34. # WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。
  35. # WITHCOORD: 将位置元素的经度和维度也一并返回。
  36. 127.0.0.1:6379> georadius china:city 117.3 40.0 100 km
  37. 1) "beijing"
  38. 127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist
  39. 1) 1) "beijing"
  40. 2) "85.9885"
  41. 3) 1) "116.30000084638595581"
  42. 2) "39.90000009167092543"
  43. 127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist withcount
  44. (error) ERR syntax error
  45. 127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist Count count
  46. (error) ERR value is not an integer or out of range
  47. 127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist Count
  48. (error) ERR syntax error
  49. 127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist count
  50. (error) ERR syntax error
  51. 127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist
  52. 1) 1) "beijing"
  53. 2) "85.9885"
  54. 3) 1) "116.30000084638595581"
  55. 2) "39.90000009167092543"
  56. ## 以给定的元素为中心,给定距离为半径查找
  57. 127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 100 km
  58. 1) "beijing"
  59. 127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km
  60. 1) "xingtai"
  61. 2) "beijing"
  62. 3) "xian"
  63. 127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km withdist
  64. 1) 1) "xingtai"
  65. 2) "352.6012"
  66. 2) 1) "beijing"
  67. 2) "0.0000"
  68. 3) 1) "xian"
  69. 2) "904.3049"
  70. #删除元素; 使用的是zset的api进行删除
  71. 127.0.0.1:6379> zrem china:city beijing
  72. (integer) 1
  73. 127.0.0.1:6379> zrange china:city 0 -1
  74. 1) "chongqing"
  75. 2) "xian"
  76. 3) "suzhou"
  77. 4) "shanghai"
  78. 5) "xingtai"

HyperLogLog

统计基数的,{1,2,3,4,5,4,3,2} 基数就是5,因为只有5个互相不通的数.

  • 用来统计有效访问人数,重复访问不算.
  • 占的内存固定,比较小

image.png

  1. 127.0.0.1:6379> PFADD mykey a b c d e f g # 添加元素到mykey集合中
  2. (integer) 1
  3. 127.0.0.1:6379> pfcount mykey # 统计基数
  4. (integer) 7
  5. 127.0.0.1:6379> PFADD mykey2 a b c d g h i j # 添加元素到mykey中
  6. (integer) 1
  7. 127.0.0.1:6379> pfcount mykey2 # 统计基数
  8. (integer) 8
  9. 127.0.0.1:6379> PFMERGE mykey3 mykey1 mykey2 # 合并
  10. OK
  11. 127.0.0.1:6379> PFCOUNT mykey3 # 统计基数
  12. (integer) 8

Bitmaps

https://www.cnblogs.com/54chensongxia/p/13794391.html
BitMap 原本的含义是用一个比特位来映射某个元素的状态。由于一个比特位只能表示 0 和 1 两种状态,所以 BitMap 能映射的状态有限,但是使用比特位的优势是能大量的节省内存空间。
在 Redis 中,可以把 Bitmaps 想象成一个以比特位为单位的数组,数组的每个单元只能存储0和1,数组的下标在 Bitmaps 中叫做偏移量。

使用场景:

  • 用户签到
  • 活跃用户
  • 用户是否在线
  1. # 设置值,其中value只能是 0 和 1
  2. setbit key offset value
  3. # 获取值
  4. getbit key offset
  5. # 获取指定范围内值为 1 的个数
  6. # start 和 end 以字节为单位
  7. bitcount key start end
  8. # BitMap间的运算
  9. # operations 位移操作符,枚举值
  10. AND 与运算 &
  11. OR 或运算 |
  12. XOR 异或 ^
  13. NOT 取反 ~
  14. # result 计算的结果,会存储在该key中
  15. # key1 … keyn 参与运算的key,可以有多个,空格分割,not运算只能一个key
  16. # 当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0。返回值是保存到 destkey 的字符串的长度(以字节byte为单位),和输入 key 中最长的字符串长度相等。
  17. bitop [operations] [result] [key1] [keyn…]
  18. # 返回指定key中第一次出现指定value(0/1)的位置
  19. bitpos [key] [value]

事务

  • redis单条命令保证原子性,事务不保证原子性
    • 事务的原子性是要么一起成功,要么一起失败
    • redis事务中如果其中一个命令错误,那么不会导致后面命令的执行,也不会导致前面命令的回滚
  • 事务不会放入一条命令就执行一条命令,而是会在exec之后按顺序执行

事务正常流程

  • 使用Multi标识开始事务Multi
  • 放入一系列的命令
  • 执行事务Exec
    1. 127.0.0.1:6379> MULTI # 开启事务标识
    2. OK
    3. 127.0.0.1:6379> set name zms
    4. QUEUED
    5. 127.0.0.1:6379> get name
    6. QUEUED
    7. 127.0.0.1:6379> lpush z1 zms
    8. QUEUED
    9. 127.0.0.1:6379> lpush z2 zms
    10. QUEUED
    11. 127.0.0.1:6379> lpop z1
    12. QUEUED
    13. 127.0.0.1:6379> lpop z2
    14. QUEUED
    15. 127.0.0.1:6379> lpop z2
    16. QUEUED
    17. 127.0.0.1:6379> EXEC # 执行事务标识
    18. 1) OK
    19. 2) "zms"
    20. 3) (integer) 1
    21. 4) (integer) 1
    22. 5) "zms"
    23. 6) "zms"
    24. 7) (nil)

事务失败

  1. 127.0.0.1:6379> MULTI
  2. OK
  3. 127.0.0.1:6379> set z zms
  4. QUEUED
  5. 127.0.0.1:6379> incr z #字符串无法无法+1,失败
  6. QUEUED
  7. 127.0.0.1:6379> set n name
  8. QUEUED
  9. 127.0.0.1:6379> exec
  10. 1) OK
  11. 2) (error) ERR value is not an integer or out of range
  12. 3) OK
  13. 127.0.0.1:6379> get n # 依然可以获取失败命令后面的命令执行
  14. "name"

取消事务

  1. 127.0.0.1:6379> multi
  2. OK
  3. 127.0.0.1:6379> get name
  4. QUEUED
  5. 127.0.0.1:6379> set name na
  6. QUEUED
  7. 127.0.0.1:6379> DISCARD # 取消事务,放弃已经输入的命令
  8. OK

  • 悲观锁
    • 认为什么时候都会有问题,无论做什么都会加锁.
  • 乐观锁
    • 认为什么时候都不会出问题,任何时候都不上锁.
    • 更新数据的时候判断一下,在此期间是否有人修改过这个数据,(mysql中是version)

Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断,事务一旦执行成功,监控自动取消
WATCH key ``[``key ``...]
只要监视到其余线程的修改,就取消事务(本线程修改就允许的)

  • 事务正常执行

    1. 127.0.0.1:6379> set money 100
    2. OK
    3. 127.0.0.1:6379> set out 0
    4. OK
    5. 127.0.0.1:6379> watch money # 监视money
    6. OK
    7. 127.0.0.1:6379> MULTI
    8. OK
    9. 127.0.0.1:6379> INCRBY out 20
    10. QUEUED
    11. 127.0.0.1:6379> DECRBY money 20
    12. QUEUED
    13. 127.0.0.1:6379> exec
    14. 1) (integer) 20
    15. 2) (integer) 80
    16. # 余额跟花费都是正确的
  • 事务失败

image.png
先设置money\out并监视
在其他线程修改
事务失败

  • 语法错误

而只要有一个命令有语法错误,执行EXEC命令后Redis就会直接返回错误,连语法正确的命令也不会执行。

  1. 127.0.0.1:6379> multi
  2. OK
  3. 127.0.0.1:6379> set name a
  4. QUEUED
  5. 127.0.0.1:6379> set na # 语法错误
  6. (error) ERR wrong number of arguments for 'set' command
  7. 127.0.0.1:6379> exec # 语法错误事务不执行
  8. (error) EXECABORT Transaction discarded because of previous errors.

watch

https://redisbook.readthedocs.io/en/latest/feature/transaction.html 写的很牛逼
WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。监控一直持续到EXEC命令(事务中的命令是在EXEC之后才执行的,所以在MULTI命令后可以修改WATCH监控的键值)

  • watch监视后,如果事务执行失败,记得解锁;.
  • image.png

整合Java

Jedis

  1. 依赖

    1. jedis
    2. fastjson ```basic

      redis.clients jedis 3.5.1 com.alibaba fastjson 1.2.75
  1. 2. 编码测试
  2. 1. 连接数据库
  3. ```basic
  4. public static void main(String[] args) {
  5. // 1. new Jedis
  6. Jedis jedis = new Jedis("localhost", 6379);
  7. System.out.println(jedis.ping());
  8. Jedis.close();
  9. }
  1. 操作命令
  2. 断开连接

配置文件Redis.conf

**/opt/redis/zmsconfig**

持久化

Redis是内存数据库,如果不讲内存中的数据库状态保存到磁盘,那么一旦服务器退出,服务器中的数据库状态也会消失,所以Redis提供了持久化的功能.

RDB

  • 最后一次持久化的数据可能丢失.
  • 比AOF高效
  • 保存的文件默认是dump.rdb文件

    AOF