Redis的基础使用

Redis 默认了16个数据库,0-15

redis key

keys * 查看所有的key

EXISTS name 判断key是否存在

move name 1 移除当前key

EXPIRE name time 设置过期时间(s)

ttl name 查看当前key的剩余时间

五大数据类型

String 字符串类型

SET key1 v1 # 设置值
keys * # 获得所有jkey
get key1 # 获得值
EXISTS key1 # 判断某个key是否存在
APPEND key1 "hello" # 追加字符串,key不存在,就新建字符串
strlen key1 # 获取字符串长度
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> INCR views # 增加1
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> DECR views # 减少1
(integer) 0
127.0.0.1:6379> get views
"0"

127.0.0.1:6379> INCRBY views 10 #步长为10的增加
(integer) 10
127.0.0.1:6379> get views
"10"
127.0.0.1:6379> DECRBY views 10 #步长为10的减少
(integer) 0
127.0.0.1:6379> get views
"0"

127.0.0.1:6379> set key1 "hello,mikuneko"
OK
127.0.0.1:6379> GET key1
"hello,mikuneko"
127.0.0.1:6379> GETRANGE key1 0 4 # 截取字符串
"hello"
127.0.0.1:6379> GETRANGE key1 0 -1 # 查看全部字符串
"hello,mikuneko"
127.0.0.1:6379> SETRANGE key1 1 xx # 替换字符串
(integer) 14
127.0.0.1:6379> GETRANGE key1 0 -1
"hxxlo,mikuneko"

127.0.0.1:6379> setex key3 30 "hello" # 设置过期时间
OK
127.0.0.1:6379> ttl key3
(integer) 22
127.0.0.1:6379> setnx key4 "mykey" # 不存在就创建
(integer) 1
127.0.0.1:6379> keys *
1) "key4"
2) "key1"
127.0.0.1:6379> ttl key4
(integer) -1
127.0.0.1:6379> setnx key4 "yourKey" # 存在了就失败
(integer) 0
127.0.0.1:6379> get key4 # 值没有被改变
"mykey"


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) "k1"
2) "k3"
3) "k2"
127.0.0.1:6379> mget k1 k2 k2 # 多项获取
1) "v1"
2) "v2"
3) "v2"
127.0.0.1:6379> msetnx k1 v1 k4 v4 #msetnx是一个原子性的操作,要么全部成功,要么全部失败
(integer) 0
127.0.0.1:6379> keys *
1) "k1"
2) "k3"
3) "k2"

# 设计一个对象: user:{id}:{filed} 设计成一个Json字符串存储对象
127.0.0.1:6379> mset user:1:name mikuneko user:1:age 2 #对象保存:json字符
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) "mikuneko"
2) "2"

127.0.0.1:6379> GETSET db redis # 先get,再set,没有值返回nil
(nil)
127.0.0.1:6379> GET db
"redis"
127.0.0.1:6379> GETSET db mongodb # 拿到的是上一个值,然后更新值
"redis"
127.0.0.1:6379> GET db
"mongodb"

String类型的使用场景: value除了是我们的字符串,还可以是数字

  1. 计数器(统计个数)

  2. 对象存储

List 列表类型

基本的数据类型,列表

在redis中,list可以变成栈,队列等

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> lpush list one # 将一个或者多个值插入到列表头部(左边)
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> Lrange list 0 -1 
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> LRANGE list 0 1 # 通过区间获取具体的值
1) "three"
2) "two"
127.0.0.1:6379> RPUSH list zero # 将一个或者多个值插入到列表尾部(右边)
(integer) 4
127.0.0.1:6379> Lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "zero"


127.0.0.1:6379> LPOP list #返回并移除列表的头部的第一个值(左边)
"three"
127.0.0.1:6379> Lrange list 0 -1
1) "two"
2) "one"
3) "zero"
127.0.0.1:6379> RPOP list #返回并移除列表的尾部的第一个值(右边)
"zero"
127.0.0.1:6379> Lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> LINDEX list 1 # 通过下标获得 list 中的某一个值
"one"
127.0.0.1:6379> LINDEX list 0
"two"
127.0.0.1:6379> LLEN list # 获得list长度
(integer) 2



127.0.0.1:6379> LPUSH  list one
(integer) 1
127.0.0.1:6379> LPUSH  list two
(integer) 2
127.0.0.1:6379> LPUSH  list three
(integer) 3
127.0.0.1:6379> LPUSH  list three
(integer) 4
127.0.0.1:6379> LREM list 1 one  # 移除list中指定的value 精确匹配
(integer) 1
127.0.0.1:6379> Lrange list 0 -1 # value是可重复的
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> LREM list 1 three
(integer) 1
127.0.0.1:6379> Lrange list 0 -1
1) "three"
2) "two"
127.0.0.1:6379> LPUSH list three
(integer) 3
127.0.0.1:6379> LREM list 2 three # 一次性移除两个
(integer) 2
127.0.0.1:6379> Lrange list 0 -1
1) "two"


127.0.0.1:6379> RPOPLPUSH list otherlist #移除最后一个元素,并添加到新的列表中
"hello3"
127.0.0.1:6379> LRANGE list 0 -1 # 查看原来的列表
1) "hello"
2) "hello1"
3) "hello2"
127.0.0.1:6379> LRANGE otherlist 0 -1 # 查看目标列表
1) "hello3"


127.0.0.1:6379> EXISTS list # 判断列表是否存在
(integer) 0
127.0.0.1:6379> LSET list 0 item # 如果不存在,更新就会报错
(error) ERR no such key
127.0.0.1:6379> lpush list value1 
(integer) 1
127.0.0.1:6379> LRANGE list 0 0
1) "value1"
127.0.0.1:6379> LSET list 0 item # 存在就会更新这个值
OK
127.0.0.1:6379> LRANGE list 0 0
1) "item"


127.0.0.1:6379> LPUSH list "hello"
(integer) 1
127.0.0.1:6379> LPUSH list "world"
(integer) 2
127.0.0.1:6379> LINSERT list before "world" "other" # 插入值
(integer) 3
127.0.0.1:6379> LRANGE list 0 -1
1) "other"
2) "world"
3) "hello"

sets 集合类型

set中的值是不能重复的

127.0.0.1:6379> sadd myset "hello" # 向set中存值
(integer) 1
127.0.0.1:6379> sadd myset "hellomiku"
(integer) 1
127.0.0.1:6379> sadd myset "hellomikuneko"
(integer) 1
127.0.0.1:6379> SMEMBERS myset # 获取set中的值
1) "hellomiku"
2) "hellomikuneko"
3) "hello"
127.0.0.1:6379> SISMEMBER myset hello # 判断是否存在值
(integer) 1
127.0.0.1:6379> SISMEMBER myset world
(integer) 0 

127.0.0.1:6379> SRANDMEMBER myset # 随机抽取一个元素
"hellomiku"
127.0.0.1:6379> SRANDMEMBER myset
"hellomikuneko"
127.0.0.1:6379> SRANDMEMBER myset 2 #随机抽取n个元素
1) "hellomikuneko"
2) "hello"


127.0.0.1:6379> SMEMBERS myset
1) "hellomiku"
2) "hello"
3) "hellomikuneko"
127.0.0.1:6379> spop myset # 随机移除元素
"hellomikuneko"
127.0.0.1:6379> SMEMBERS myset
1) "hellomiku"
2) "hello"


127.0.0.1:6379> sadd myset "hello"
(integer) 1
127.0.0.1:6379> sadd myset "world"
(integer) 1
127.0.0.1:6379> sadd myset "wooo"
(integer) 1
127.0.0.1:6379> sadd myset2 "eee"
(integer) 1 
127.0.0.1:6379> SMOVE myset myset2 "world" # 移动元素到指定的集合中
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "hello"
2) "wooo"
127.0.0.1:6379> SMEMBERS myset2
1) "world"
2) "eee"
127.0.0.1:6379> SDIFF myset myset2 # 查看差集
1) "hello"
2) "wooo"
127.0.0.1:6379> SINTER myset myset2 # 查看交集
(empty array)
127.0.0.1:6379> SUNION myset myset2 # 查看并集
1) "world"
2) "eee"
3) "hello"
4) "wooo"

把所有关注的人放在set中,粉丝放在set中,共同关注,二度好友

Hash 哈希类型

Map集合,key-map 值是一个map集合

127.0.0.1:6379> hset myhash field1 mikuneko
(integer) 1
127.0.0.1:6379> hget myhash field1
"mikuneko"
127.0.0.1:6379> hmset myhash field1 mika field2 miku 
OK
127.0.0.1:6379> hmget myhash field1 field2
1) "mika"
2) "miku"
127.0.0.1:6379> HGETALL myhash
1) "field1"
2) "mika"
3) "field2"
4) "miku"
127.0.0.1:6379> HDEL myhash field1
(integer) 1
127.0.0.1:6379> HGETALL myhash
1) "field2"
2) "miku"
127.0.0.1:6379> hmset myhash field1 hello field2 huhu field3 lala
OK
127.0.0.1:6379> HLEN myhash
(integer) 3
127.0.0.1:6379> HEXISTS myhash field1
(integer) 1
127.0.0.1:6379> HKEYS myhash
1) "field2"
2) "field1"
3) "field3"
127.0.0.1:6379> HVALS myhash
1) "huhu"
2) "hello"
3) "lala"
127.0.0.1:6379> hset myhash num 5
(integer) 1
127.0.0.1:6379> HINCRBY myhash num 2
(integer) 7
127.0.0.1:6379> HGET myhash num
"7"
127.0.0.1:6379> HINCRBY myhash num -3
(integer) 4
127.0.0.1:6379> HGET myhash num
"4"
127.0.0.1:6379> HSETNX myhash field4 hello
(integer) 1
127.0.0.1:6379> HSETNX myhash field4 mybaby
(integer) 0
127.0.0.1:6379> HGET myhash field4
"hello"

hash变更的数据 user name age ,尤其是用户信息之类的经常变动的信息

Zset 有序集合

在set的基础上增加了一个值

127.0.0.1:6379> zadd myzset 1 one
(integer) 1
127.0.0.1:6379> zadd myzset 2 two 3 three
(integer) 2
127.0.0.1:6379> ZRANGE myzset 0 -1
1) "one"
2) "two"
3) "three"

127.0.0.1:6379> zadd salary 2000 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 5000 lisi
(integer) 1
127.0.0.1:6379> zadd salary 200 wangwu
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf #从小到大排序
1) "wangwu"
2) "zhangsan"
3) "lisi"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores
1) "wangwu"
2) "200"
3) "zhangsan"
4) "2000"
5) "lisi"
6) "5000"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 2500 withscores
1) "wangwu"
2) "200"
3) "zhangsan"
4) "2000"
127.0.0.1:6379> zrem salary wangwu
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf
1) "zhangsan"
2) "lisi"
127.0.0.1:6379> ZCARD salary # 获取有序集合中的个数
(integer) 2

127.0.0.1:6379> ZREVRANGE salary 0 -1 # 从大到小排序
1) "lisi"
2) "zhangsan"

三种特殊数据类型

geopatial 地理位置

可以推算地理位置的信息,两地之间的距离,方圆几里的人

127.0.0.1:6379> GEOADD china:city 104.125699 30.575409 chengdu
(integer) 1
127.0.0.1:6379> GEOADD china:city 116.496305 39.870876 beijing
(integer) 1
127.0.0.1:6379> GEOADD china:city 121.528043 24.999898 taibei
(integer) 1
127.0.0.1:6379> GEOADD china:city 114.37045 22.282895 xianggang
(integer) 1
127.0.0.1:6379> GEOADD china:city 113.447599 23.214995 guangzhou
(integer) 1
127.0.0.1:6379> GEOADD china:city 121.533536 31.14127 shanghai
(integer) 1
# 两级无法直接添加,一般下载数据用java导入
# GEOADD china:city 121.533536 31.14127 shanghai (纬度 经度 名称)

127.0.0.1:6379> GEOPOS china:city beijing taibei # 获取纬度和经度(坐标值)
1) 1) "116.49630635976791382"
   2) "39.87087614555012038"
2) 1) "121.52804464101791382"
   2) "24.9998977633339905"

127.0.0.1:6379> GEODIST china:city beijing taibei km # 两个地点之间的直线距离
"1719.3478"
127.0.0.1:6379> GEODIST china:city beijing taibei m
"1719347.7590"

# 附近的人:获得附近的人的地址(定位),通过半径来查询
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km
1) "chengdu"
2) "xianggang"
3) "guangzhou"
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km withcoord withdist # 以110 30 这个经纬度为中心,寻找方圆1000km以内的城市
1) 1) "chengdu"
   2) "567.7443"
   3) 1) "104.12570089101791382"
      2) "30.57540983507971077"
2) 1) "xianggang"
   2) "962.6388"
   3) 1) "114.37045186758041382"
      2) "22.28289466654234019"
3) 1) "guangzhou"
   2) "828.7512"
   3) 1) "113.44760030508041382"
      2) "23.21499528262952339"
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km withcoord withdist count 1 #限制只查一个
1) 1) "chengdu"
   2) "567.7443"
   3) 1) "104.12570089101791382"
      2) "30.57540983507971077"

127.0.0.1:6379> GEORADIUSBYMEMBER china:city xianggang 1000 km # 用member查询
1) "xianggang"
2) "guangzhou"
3) "taibei"


# 返回给的一个地理位置hash字符串(二维转一维度,字符串约接近,距离越接近)
127.0.0.1:6379> GEOHASH china:city xianggang taibei
1) "wecqf86p280"
2) "wsqqjrn4bw0"

#geo的底层就是Zset,所以我们可以使用zset的命令来操作geo
127.0.0.1:6379> ZRANGE china:city 0 -1 # 查看地图所有元素
1) "chengdu"
2) "xianggang"
3) "guangzhou"
4) "taibei"
5) "shanghai"
6) "beijing"

hyperloglog 技术统计(有错误率)

什么是基数?

A{1,3,5,7,8,7}

B{1,3,5,7,8}

基数: 不重复的元素=5,可以接受误差

redis 2.8.9就更新了hyperloglog数据结构

网页的UV: 一个人访问网站多次,还是算一个人

传统的方式,set,保存用户的id,然后统计。如果保存大量的用户ID,就会比较麻烦,目的是为了计数,不是保存用户ID

hyperloglog占用的内存是固定的,2^64不同元素的基数,只需要12k的内存

127.0.0.1:6379> PFADD mykey a b c d e f g h i j # 插入第一组元素
(integer) 1
127.0.0.1:6379> PFCOUNT mykey # 统计数据
(integer) 10
127.0.0.1:6379> PFadd  mykey2 a d s w r g e e e e# 插入第二组元素
(integer) 1
127.0.0.1:6379> PFCOUNT mykey2 # 统计去重之后的,所以只有7个
(integer) 7
127.0.0.1:6379> PFMERGE mykey3 mykey2 mykey #合并两组元素,到新的组(并集)
OK
127.0.0.1:6379> PFCOUNT mykey3 # 统计也是去重之后的数据
(integer) 13

bitmaps 位存储

只用0和1就能解决,统计用户信息:是否登录,是否打卡,是否活跃(两个状态)

位图数据结构

# 使用位图记录周一到周日的打卡
127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 0
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
127.0.0.1:6379> setbit sign 4 0
(integer) 0
127.0.0.1:6379> setbit sign 5 1
(integer) 0
127.0.0.1:6379> setbit sign 6 1
(integer) 0

#查看周四有没有打卡
27.0.0.1:6379> GETBIT sign 3
(integer) 1

#查看有几天的数据是1
127.0.0.1:6379> BITCOUNT sign 
(integer) 4

事务

MYSQl : ACID

redis 单条命令保证原子性,但是事务不保证原子性

REDIS事务本质:

一组命令的集合,一个事务中的所有命令都会被序列化,在任务执行的过程中,会按照顺序执行

一次性,顺序性,排他性执行一系列的命令

---------- 队列 set set set 执行------------

Redis事务没有隔离级别的概念

所有命令在食物中,并没有被直接执行,只有发起执行命令的时候才会执行

redis 单条命令保证原子性,但是事务不保证原子性

redis的事务:

  1. 开启事务 multi

  2. 命令入队

  3. 执行事务 exec

127.0.0.1:6379> multi	#开启事务		
OK
127.0.0.1:6379(TX)> set k1 vi	#命令入队
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> exec #执行事务
1) OK
2) OK
3) OK
  1.  放弃事务 DISCARD:

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 vi
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> DISCARD
OK
127.0.0.1:6379> get k4
(nil)

队列中的命令都没有被执行

redis命令错误:

  1. 编译型异常: 就是代码有问题,编译出错,那么这个队列所有的命令都不会执行。

127.0.0.1:6379> multi	# 开启事务
OK
127.0.0.1:6379(TX)> set k1 vi 
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> getset k3 # 发生错误
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> set k5 v5
QUEUED
127.0.0.1:6379(TX)> EXEC # 执行事务
(error) EXECABORT Transaction discarded because of previous errors. # 发生异常
127.0.0.1:6379> get k5 # 所有的命令都没有执行
(nil)
  1. 运行时异常: 如果队列中有与发行错误,执行命令的时候其他命令是可以正常执行的。错误命令抛出异常。

127.0.0.1:6379> set k1 "v1" 
OK
127.0.0.1:6379> MULTI # 开启事务
OK
127.0.0.1:6379(TX)> INCR k1 # 自增一个String,会报错
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> EXEC # 执行事务
1) (error) ERR value is not an integer or out of range # 抛出错误
2) OK
3) OK
127.0.0.1:6379> get k2 # 其他命令正常执行
"v2"

锁: redis实现乐观锁(监控)

悲观锁: 认为什么时候都会出问题

乐观锁: 认为不会出问题,不会上锁,更新数据的时候判断一下,是否有人改过数据

监视器: watch

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money #监视器-》money
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> DECRBY money 30
QUEUED
127.0.0.1:6379(TX)> INCRBY out 30
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 70
2) (integer) 30

# 正常执行成功,数据没有发生变动

# 如果线程2修改了钱,修改了money ,事务提交就会失败,返回nil
# watch的时候会拿到这个money的值,然后再修改的时候回去进行比较,如果值被改变了,就事务提交失败。

事务执行失败:

  1. 解锁 : unwatch,然后再进行操作

  2. 再次监视,获取最新的值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PigeonEssence

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值