特点
1.基于内存存储,读写性能高 key-value结构的数据库
2.适合存储热点数据(热点商品,咨询,新闻,访问量大的数据)
设置密码 redis.windows.conf
重新连接 redis-cli.exe -a 123456
测试连接 keys *
一、5种数据类型
字符串string 哈希hash 列表list 集合set 有序集合sorted set/zset
hash 散列 类似于HashMap
list 列表 按照插入顺序排序 可重复 类似于LinkedList
set 集合 无序集合 无重复元素 类似HashSet
有序集合 zset 每个元素关联一个分数score 根据分数升序排列,无重复
常用命令
1.字符串类型
-
SET key value 设置key的value
-
GET key 获取value
-
SETEX key seconds value 设置key的值,并设置seconds秒过期
-
SETNX key value 只有在key不存在时设置value
-
APPEND key1 'hello' 追加
-
STRLEN key1
-
自增 SET key10 , incr key1
-
自减 decr
-
指定步长 INCRBY key110
-
GETRANGE key1 0 3
-
SetRange key1 1 xx , (key1=abcdefg) 变成(key1=axxdefg)
-
mset k1 v1 k2 v2 批量设置
-
msetnx 要么一起成功 要么一起失败
-
mset user:1:name zhansgan user:1:age 18 ,可以这样设置对象
-
mget user:1:name user:1:age
-
getset ,先get再set
2.HASH哈希操作命令
使用场景:最多的应用是存储变更的数据,尤其是用户信息,经常变动的信息,适合对象的存储。
-
HSET key field value 设置哈希表key中字段field的值为value,field存在则覆盖
-
HGET key field 获取字段值
-
HDEL key field 删除
-
HMSET key field1 v1 field2 v2 field v3 批量设置
-
HMGET key field1 field2 field3 批量获取值
-
HKEYS key 获取哈希表中所有字段field
-
HVALS key 获取哈希表中所有的值value
-
HGETALL key获取全部数据
-
HLEN key 获取字段数量
-
HEXISTS key field 判断HASH中指定字段是否存在
-
HINCRBY key field 5 设置增量5,field=field+5
-
HSETNX key field v1 若key已存在则失败,返回0,成功返回1
3.列表操作命令
可以玩成栈,队列,阻塞队列
-
LPUSH key value1 [value2] 将一个或多个值插入到列表头部
-
LRANGE key start stop 获取指定范围的元素
-
LRANGE key 0 -1查看key内所有元素
-
RPOP key 移除并获取最后一个元素
-
LPOP key 移除并获取第一个元素
-
LLEN key 获取列表长度
-
LINDEX key 0 获取第0个元素
-
LREM key 2 v1 移除2个值为v1的元素,精确匹配
-
LTRIM key 0 1 截取指定位置(闭区间),只剩下截取的元素(第0个和第1个)
-
rpoplpush key1 key2 移除key1最右边的元素,把它加入到key2的最左边
-
Lset key 0 v1 设置第0个元素为v1,下标不存在则报错
-
Linsert key before v1 hello 在v1前面插入hello
-
Linsert key after v1 hello 在v1后面插入hello
4.Set无序不重复集合操作命令
使用场景:共同关注,交集
-
SADD key member1 [member2] 添加一个或多个成员
-
SMEMBERS key 返回所有成员
-
SIsMember key v1 判断key中是否存在v1,存在返回1,不存在返回0
-
SCARD key 获取集合成员数
-
SREM key member1 [member2] 删除一个或多个成员
-
SRANDMEMBER key 随机选出一个元素
-
SRANDMEMBER key 2 随机选出两个元素
-
SPOP key 随机删除key中的一个元素
-
SMOVE key1 key2 v1 把key1中的v1移动到key2内
-
SINTER key1 [key2] 返回给定 所有集合的交集
-
SUNION key1 [key2] 返回并集
-
SDIFF set1 set2 差集,以set1为主,查看与set2集合不同的元素
-
存储对象:hset user:1 name zhangsan
5.有序集合 zset
使用场景:对成绩表工资表排序等等,也可以根据权重判断,也可以实现排行榜
-
ZADD key score1 member1 [score2 member2] 添加一个或多个元素
-
ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合中指定区间内的成员,并且显示SCORE
-
全部显示和分数 zrange zset 0 -1 withscores
-
ZINCRBY key increment member 有序集合中指定成员的分数加上增量increment
-
ZREM key member [member...] 移除有序集合中的一个或多个
-
ZRANGEBYSCORE key -inf +inf 根据key字段升序-inf +inf表示负无穷到正无穷
-
ZRANGEBYSCORE key +inf -inf 根据key字段降序
-
ZCARD key 获取有序集合中元素的个数
-
ZCOUNT key 0 1000 获取key中指定0~1000区间的元素个数
6.通用命令
-
KEYS pattern 查找所有符合给定模式的key keys * , keys set*
-
EXISTS key 检查是否存在
-
TYPE key 返回key存储的值的类型
-
DEL key 存在时删除key
二、三种特殊数据类型
1.Geospatial地理位置
可以用于推算地理位置信息,两地之间的距离,方圆几里的人。
-
geoadd china:city 116.405285 39.90498 beijing 添加地理位置
-
geoadd china:city 114.298572 30.584355 wuhan
-
geoadd china:city 118.767413 32.04154 nanjing
-
geopos china:city wuhan 获得当前坐标1) 1) "114.29857403039932251" 2) "30.58435486605102227"
-
geodist china:city beijing nanjing [单位], 输出"899992.6369",获得beijing与nanjing之间的距离,默认单位m,可选km千米,mi英里,ft英尺
-
georadius china:city 110 30 1000 km,以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
-
WITHDIST:在返回位置元素的同时,将位置元素与中心之间的距离也一并返回。距离的单位和用户给定的范围单位保持一致。
-
WITHCOORD:将位置元素的经度和维度也一并返回。
-
WITHHASH:以52位有符号整数的形式,返回位置元素经过原始geohash编码的有序集合分值。这个选项主要用于底层应用或者调试,实际中的作用并不大。
-
ASC:根据中心的位置,按照从近到远的方式返回位置元素。
-
DESC:根据中心的位置,按照从远到近的方式返回位置元素。
-
-
georadius china:city 110 30 500 km withcoord1) 1) "chongqing" 2) 1) "106.50495976209640503" 2) "29.53315530684997015"
-
georadius china:city 110 30 500 km withdist1) 1) "wuhan" 2) "417.8920"
-
georadius china:city 110 30 500 km withcoord withdist count 11) 1) "chongqing" 2) "341.4052" 3) 1) "106.50495976209640503" 2) "29.53315530684997015"
-
georadius china:city 110 30 1000 km desc1) "nanjing"2) "wuhan"
-
GEORADIUSBYMEMBER china:city beijing 1000 km,根据位置元素找出位于指定范围内的元素1) "nanjing"2) "beijing"
-
GEO 底层的实现原理其实就是 Zset
-
zrange china:city 0 -1,查看地图中全部的元素
-
zrem china:city aomen 移除指定元素
2.Hyperloglog基数统计
使用场景:网页的页面访问量(UV)(例如,一个人访问一个网站多次,但是还是算作一个人)。
传统的方式:set(无序不重复)保存用户的id,然后就可以统计 set 中的元素数量作为标准判断。这个方式如果保存大量的用户id,比较麻烦,占内存, 我们的目的是为了计数,而不是保存用户id。
现在的方式:可以使用 Hyperloglog进行存储,占用的内存是固定,2^64 不同元素的基数,只需要12KB内存。如果要从内存角度来比较的话Hyperloglog首选。可能会出现0.81%的 错误率,统计UV任务时,是可以忽略不计的。
-
PFADD my1 a b c d e f g h i j k
-
PFCOUNT my1,输出11
-
PFADD my2 j k l m n a d e o p
-
PFCOUNT my2,输出10
-
PFMERGE my3 my1 my2,合并my1,my2成为my3
-
PFCOUNT my3,输出16
3.Bitmap
使用场景:统计用户信息,活跃 或 不活跃、 登录 或 未登录、 打卡 或 未打卡。涉及两个状态的,都可以使用Bitmap位存储。
127.0.0.1:6379> setbit ding 1 1(integer) 0127.0.0.1:6379> setbit ding 2 1(integer) 0127.0.0.1:6379> setbit ding 3 0(integer) 0127.0.0.1:6379> setbit ding 4 1(integer) 0127.0.0.1:6379> setbit ding 5 1(integer) 0127.0.0.1:6379> setbit ding 6 0(integer) 0127.0.0.1:6379> setbit ding 7 0(integer) 0
查看某一天是否有打卡,返回1则打卡,返回0则未打卡
127.0.0.1:6379> getbit ding 2(integer) 1127.0.0.1:6379> getbit ding 3(integer) 0
统计操作,统计打卡的天数,即统计这周的打卡记录,就可以看到是否有全勤
127.0.0.1:6379> bitcount ding(integer) 5
三、性能测试
redis-benchmark
docker 中,docker exec -it myredis bash交互式进入redis
redis-benchmark -c 100 -n 100000,100个并发,10w个请求
四、Redis事务
1、事务特性
一次性:开启事物后,会在一个队列中一次性执行。
顺序性:会在队列中按照入队顺序执行。
排他性:事物执行过程中不允许其他线程干扰。
注意
1.Redis单条命令保存原子性,但事物不保证原子性。
2.Redis事物没有隔离级别概念。
3.所有命令在事务中,并没有直接被执行,只有发起命令Exec时才会执行。
2、Redis的事务
1.开启事务(multi) 2.命令入队(set/get) 3.执行事务(exec)、放弃事务(DISCARD)
# 开启事务
127.0.0.1:6379> multi
OK
# 命令入队
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
127.0.0.1:6379> get k2
QUEUED
127.0.0.1:6379> set k3 v3
QUEUED
# 按一次性、顺序性、排他性特性,执行事务
127.0.0.1:6379> exec
1) OK
2) OK
3) "v2"
4) OK
3、编译时异常
# 编译型异常(代码有问题, 命令有错),事务中所有的命令都不会被执行。
# 开启事务
127.0.0.1:6379> multi
OK
# 命令入队
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
# 出现错误命令,发生编译型异常,事务中所有命令都不会被执行
127.0.0.1:6379> setget k3 v3
(error) ERR unknown command `setget`, with args beginning with: `k3`, `v3`,
127.0.0.1:6379> set k4 v4
QUEUED
# 执行事务时报错
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
# 获取值,返回为null
127.0.0.1:6379> get k1
(nil)
127.0.0.1:6379> get k4
(nil)
4、运行时异常
# 编译型异常(代码有问题, 命令有错),事务中所有的命令都不会被执行。
# 开启事务
127.0.0.1:6379> multi
OK
# 命令入队
127.0.0.1:6379> set k1 v1
QUEUED
127.0.0.1:6379> set k2 v2
QUEUED
# 出现错误命令,发生编译型异常,事务中所有命令都不会被执行
127.0.0.1:6379> setget k3 v3
(error) ERR unknown command `setget`, with args beginning with: `k3`, `v3`,
127.0.0.1:6379> set k4 v4
QUEUED
# 执行事务时报错
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
# 获取值,返回为null
127.0.0.1:6379> get k1
(nil)
127.0.0.1:6379> get k4
(nil)
5、Redis实现乐观锁
执行监视watch某个值时,即获取当前值;在执行事务exec时需要更新值,此时需要与之前获取的值做比较。
# 第一个客户端:开启监视money,开启事务,修改值
127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
# 监视:使用watch可以当做redis的乐观锁操作
127.0.0.1:6379> watch money
OK
# 开启事务
127.0.0.1:6379> multi
OK
# 修改值
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
# 执行事务之前,另外一个线程修改了值,会导致事务执行失败,返回nil
127.0.0.1:6379> exec
(nil)
# 第二个客户端:修改监视的值
[root@iZuf67rdcsn46d295zbgomZ ~]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> get money
"100"
127.0.0.1:6379> set money 1000
OK
若事务执行失败,则先解锁,再重新监视,即获取最新的值。
# 若事务执行失败,先解锁,放弃监视
127.0.0.1:6379> unwatch
OK
# 再开启监视,即获取最新的值select version
127.0.0.1:6379> watch money
OK
# 开启事务
127.0.0.1:6379> multi
OK
# 操作值
127.0.0.1:6379> decrby money 20
QUEUED
127.0.0.1:6379> incrby out 20
QUEUED
# 执行事务,比对监视的值是否发生变化,若没有变化则可以执行成功,若变化了则执行失败
127.0.0.1:6379> exec
1) (integer) 980
2) (integer) 20