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

基本操作
127.0.0.1:6379> select 0 # 选择0号数据库,可以从0-15OK127.0.0.1:6379> keys * # 该数据库的所有key(empty array)127.0.0.1:6379> set name zs # name = zsOK127.0.0.1:6379> keys *1) "name"127.0.0.1:6379> flushall # 清空所有的数据库OK127.0.0.1:6379> set name zmsOK127.0.0.1:6379> keys *1) "name"127.0.0.1:6379> get name #获取名字"zms"127.0.0.1:6379> EXISTS nam # 是否存在一个key,0代表不存在(integer) 0127.0.0.1:6379> EXISTS name # 1代表存在(integer) 1127.0.0.1:6379> move name(error) ERR wrong number of arguments for 'move' command127.0.0.1:6379> move name 1 #移除key(integer) 1127.0.0.1:6379> keys *(empty array)127.0.0.1:6379> set name zmsOK127.0.0.1:6379> expire name 10 #设置过期时间,10s(integer) 1127.0.0.1:6379> ttl name(integer) 8127.0.0.1:6379> ttl name # 剩余的生命周期(integer) 7127.0.0.1:6379> ttl name(integer) 6127.0.0.1:6379> ttl name(integer) 6127.0.0.1:6379> ttl name(integer) 4127.0.0.1:6379> keys *1) "name"127.0.0.1:6379> keys *(empty array)127.0.0.1:6379> set name zmsOK127.0.0.1:6379> type name #查看key的类型string
类型
String
127.0.0.1:6379> get name"zms"127.0.0.1:6379> APPEND name "XY" # 添加值,如果key不存在相当于新建(integer) 5127.0.0.1:6379> get name"zmsXY"127.0.0.1:6379> SUBSTR name 1 2 # name[1:2]的子串"ms"127.0.0.1:6379>
自增操作:
127.0.0.1:6379> set name 0OK127.0.0.1:6379> incr name(integer) 1127.0.0.1:6379> incr name # 自增1(integer) 2127.0.0.1:6379>127.0.0.1:6379> set name 0OK127.0.0.1:6379> incr name(integer) 1127.0.0.1:6379> incr name(integer) 2127.0.0.1:6379> decr name # --1(integer) 1127.0.0.1:6379> decr name127.0.0.1:6379>127.0.0.1:6379> set name 0OK127.0.0.1:6379> INCRBY name 10 #设定步长(integer) 10
字符串范围
127.0.0.1:6379> set name hello,WorldOK127.0.0.1:6379> GETRANGE name 0 2 #name[0:2]"hel"127.0.0.1:6379> GETRANGE name 0 -1 #-1代表整个串"hello,World"127.0.0.1:6379> SETRANGE name 1 xx # index=1开始替换子串(integer) 11
存在或不存在情况的设置值
127.0.0.1:6379> SETEX name 10 hello # 设置name的过期时间10sOK127.0.0.1:6379> ttl name(integer) 8127.0.0.1:6379> ttl name(integer) 7127.0.0.1:6379> SETNX mykey redis #不存在则设置值;;;;;分布式锁常用(integer) 1127.0.0.1:6379> get mykey"redis"127.0.0.1:6379> setnx mykey zms #不存在则设置,存在就不设置了(integer) 0 #返回0,设置失败127.0.0.1:6379> get mykey"redis"
批量set、get
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 一次性设置多个keyOK127.0.0.1:6379> mget k1 k2 k3 # 一次性获取多个key1) "v1"2) "v2"3) "v3"127.0.0.1:6379> msetnx k1 v1 k5 v5 # 这个操作是原子性的,要么多个key一起成功,要么一起失败(integer) 0127.0.0.1:6379> get k5 # 获取失败(nil)
设置对象
127.0.0.1:6379> set user:1 {name:zms,age:3} #id为1的userOK127.0.0.1:6379> get user:1"{name:zms,age:3}"127.0.0.1:6379> mset user:1:name xy user:1:age 23 #user:{id}:{field}OK127.0.0.1:6379> get user:1"{name:zms,age:3}"127.0.0.1:6379> mget user:1:name user:1:age1) "xy"2) "23"
先得到get再设置set
127.0.0.1:6379> getset name zs # 原本没有name,获取不到,然后设置name=zs(nil)127.0.0.1:6379> get name"zs"127.0.0.1:6379> getset name wu"zs"127.0.0.1:6379> get name"wu"
使用场景
value除了字符串还可以作为数字
- 计数器
 - 统计多单位的数量
 - 粉丝数
 - 对象缓存存储
 
List
- 可以用来实现队列、栈
 - 所有的list命令都是用’L’、’R’开头的
删除元素127.0.0.1:6379> LPUSH l1 one #将one加入l1的列表 ,在最左边加入(integer) 1127.0.0.1:6379> LPUSH l1 two(integer) 2127.0.0.1:6379> LPUSH l1 three(integer) 3127.0.0.1:6379> lrange l1 0 -1 #获取l1的全部元素1) "three" # 按栈的结构来的2) "two"3) "one"127.0.0.1:6379> lrange l1 0 1 # 获取range1) "three"2) "two"127.0.0.1:6379> rpush l1 go #在右边加入列表(integer) 4127.0.0.1:6379> lrange l1 0 -11) "three"2) "two"3) "one"4) "go"
按索引访问127.0.0.1:6379> lpush l1 1 #左边加入(integer) 1127.0.0.1:6379> lpush l1 2(integer) 2127.0.0.1:6379> lpush l1 3(integer) 3127.0.0.1:6379> rpush l1 4 # 3 2 1 4 # 右边加入(integer) 4127.0.0.1:6379> lpop l1 # 删除左边的元素"3"127.0.0.1:6379> rpop l1 # 删除右边的元素"4"
返回长度127.0.0.1:6379> lrange l1 0 -11) "2"2) "1" # 2 1127.0.0.1:6379> lindex l1 1 # 获取左边下边为1的值,没有rindex"1"
移除指定值,类似取消关注127.0.0.1:6379> lrange l2 0 -11) "three"2) "two"3) "one"127.0.0.1:6379> Llen l2 # 获取长度 Listlen(integer) 3
lrem
```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”
修剪trim,截断```bash127.0.0.1:6379> lrange l3 0 -11) "two"2) "one"3) "three"4) "four" # two one three four127.0.0.1:6379> ltrim l3 1 2 # 只保留[1:2]的元素OK127.0.0.1:6379> lrange l3 0 -11) "one"2) "three"
从本列表删除并将其移动到新的列表中
127.0.0.1:6379> lrange l3 0 -11) "one"2) "three"127.0.0.1:6379> rpoplpush l3 l4 # 删除l3的最后一个元素并加入到l4中"three"127.0.0.1:6379> lrange l3 0 -11) "one"127.0.0.1:6379> lrange l4 0 -11) "three"
更新操作
127.0.0.1:6379> EXISTS list #不存在(integer) 0127.0.0.1:6379> lset list 0 item # 不存在则无法更新(error) ERR no such key127.0.0.1:6379> lpush list index0(integer) 1127.0.0.1:6379> lrange list 0 -11) "index0"127.0.0.1:6379> lset list 0 newintem # 更新index=0位置的值OK127.0.0.1:6379> lrange list 0 -11) "newintem"
在特定元素之前之后插入
127.0.0.1:6379> rpush list hello(integer) 1127.0.0.1:6379> rpush list world(integer) 2127.0.0.1:6379> linsert list after hello XY # 在hello后面插入xy(integer) 3127.0.0.1:6379> lrange list 0 -11) "hello"2) "XY"3) "world"127.0.0.1:6379> linsert list before hello ZMS # 在hello前面插入zms(integer) 4127.0.0.1:6379> lrange list 0 -11) "ZMS"2) "hello"3) "XY"4) "world"
Set
- 值不能重复
 - 命令以s开头
- SADD 添加元素
 - SCARD set里面数据的数量
 - SDIFF 两个set取差集
 - SDIFFSTORE 结果放入指定的set中
 - SINTER 取交集
 - SINTERSTORE
 - SISMEMBER 判断一个元素是不是set的元素
 - SMEMBERS 显示所有元素
 - SMISMEMBER
 - SMOVE 从一个set讲一个元素移动到另一个元素
 - SPOP 随机移除一个
 - SRANDMEMBER 随机取一个
 - SREM 删除指定
 - SSCAN
 - SUNION 取并集
 - SUNIONSTORE
 
 
添加、判断、长度、移除
127.0.0.1:6379> sadd myset hello(integer) 1127.0.0.1:6379> sadd myset go(integer) 1127.0.0.1:6379> sadd myset go(integer) 0127.0.0.1:6379> smembers myset # 显示所有成员1) "hello"2) "go"127.0.0.1:6379> sismember myset go # go是不是myset的元素(integer) 1127.0.0.1:6379> scard myset # 长度(integer) 2
移除
127.0.0.1:6379> SMEMBERS myset1) "hello"2) "go"127.0.0.1:6379> srem myset hello(integer) 1
随机抽取一个,可以做抽奖
127.0.0.1:6379> SRANDMEMBER myset"4"127.0.0.1:6379> SRANDMEMBER myset"1"
随机删除一个
127.0.0.1:6379> spop myset"4"127.0.0.1:6379> spop myset"5"127.0.0.1:6379> scard myset(integer) 4
交集 并 差集
127.0.0.1:6379> sadd s1 1(integer) 1127.0.0.1:6379> sadd s1 2(integer) 1127.0.0.1:6379> sadd s1 3(integer) 1127.0.0.1:6379> sadd s2 3(integer) 1127.0.0.1:6379> sadd s2 4(integer) 1127.0.0.1:6379> sadd s2 5(integer) 1127.0.0.1:6379> SINTER s1 s2 # 交集1) "3"127.0.0.1:6379> sdiff s1 s2 # 差集1) "1"2) "2"127.0.0.1:6379> SUNION s1 s2 # 并集1) "1"2) "2"3) "3"4) "4"5) "5"
取出并放入
127.0.0.1:6379> SMOVE s1 s2 1 # 从s1移除出1放入s2(integer) 1127.0.0.1:6379> SMEMBERS s2 # s2的所有元素1) "1"2) "3"3) "4"4) "5"127.0.0.1:6379> SMEMBERS s1 # s1的所有元素1) "2"2) "3"
hash
hash适合存储对象
Related commands
127.0.0.1:6379> hset h1 name zms # 给H1的hash设置name=zms键值对(integer) 1127.0.0.1:6379> hget h1 name # 读取"zms"127.0.0.1:6379> hmset h1 name vms age 20 par xy # 一次设置多个OK127.0.0.1:6379> hgetall h1 # 获取h1存储的所有的1) "name"2) "vms"3) "age"4) "20"5) "par"6) "xy"127.0.0.1:6379> HEXISTS h1 name # h1是否存在name属性(integer) 1127.0.0.1:6379> HEXISTS h1 name(integer) 1127.0.0.1:6379> HEXISTS h1 nam(integer) 0127.0.0.1:6379> HINCRBY h1 name 1 # 给h1的name属性的值+1(error) ERR hash value is not an integer127.0.0.1:6379> HINCRBY h1 age 1(integer) 21127.0.0.1:6379> HINCRBY h1 age -1(integer) 20127.0.0.1:6379> hlen h1 # h1元素的长度(integer) 3127.0.0.1:6379> hkeys h1 # 所有的key1) "name"2) "age"3) "par"127.0.0.1:6379> HVALS h1 #所有的val1) "vms"2) "20"3) "xy"127.0.0.1:6379> hsetnx h1 name zs # 如果不存在则设置值(integer) 0127.0.0.1:6379> hget h1 name # 获取值"vms"127.0.0.1:6379> hsetnx h1 na zs #不存在则设置(integer) 1127.0.0.1:6379> hget h1 na"zs"127.0.0.1:6379> hstrlen h1 na # 获取na对应的val的长度(integer) 2127.0.0.1:6379> hstrlen h1 name(integer) 3
ZSet
127.0.0.1:6379> zadd z1 1 zms # 给z1加入一个元素,zms的分值是1(integer) 1127.0.0.1:6379> zadd z1 2 vms(integer) 1127.0.0.1:6379> zadd z1 3 xy 4 py # 一次加入多个(integer) 2127.0.0.1:6379> zcard z1 # 数量(integer) 4127.0.0.1:6379> zcount z1 1 3 # z1中分数在[1,3]的数量(integer) 3127.0.0.1:6379> zincrby z1 1 zms # 给zms对应的score+1"2"127.0.0.1:6379> zcount z1 1 2 #[1,2]的数量(integer) 2127.0.0.1:6379> zrange z1 0 -1 # 不带分数的查询所有1) "vms"2) "zms"3) "xy"4) "py"127.0.0.1:6379> zrange z1 0 -1 withscores # 查询所有,同时显示分数1) "vms"2) "2"3) "zms"4) "2"5) "xy"6) "3"7) "py"8) "4"127.0.0.1:6379> ZRANGEBYSCORE z1 0 3 # [0,3]分数的1) "vms"2) "zms"3) "xy"127.0.0.1:6379> ZRANGEBYSCORE z1 -inf +inf # 负无穷到正无穷分数的1) "vms"2) "zms"3) "xy"4) "py"127.0.0.1:6379> ZRANGEBYSCORE z1 -inf 2 #3 分数<2的1) "vms"2) "zms"127.0.0.1:6379> zrem z1 zms # 从z1中删除zms(integer) 1127.0.0.1:6379> ZREVRANGE z1 1 21) "xy"2) "vms"127.0.0.1:6379> ZREVRANGE z1 2 1(empty array)127.0.0.1:6379> zscore z1 vms # 获取元素对应到score"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的命令
## GEOADD key longitude latitude member [longitude latitude member ...]## GeoADD key 经 纬度 成员名称 可以添加多个127.0.0.1:6379> GEOADD china:city 116.3 39.9 beijing 121.4 31.2 shanghai 108.9 34.3 xian(integer) 3127.0.0.1:6379> geoadd china:city 106 29 chongqing 114.4 37.1 xingtai 120.6 31.1 suzhou(integer) 3127.0.0.1:6379> geopos china:city xian # 获取元素的位置1) 1) "108.90000075101852417"2) "34.30000007880482116"127.0.0.1:6379> geopos china:city xingtai1) 1) "114.39999908208847046"2) "37.10000008523787329"## GEODIST key member1 member2 [m|km|ft|mi]127.0.0.1:6379> GEODIST china:city xian chongqing km # 获取距离"650.2195"127.0.0.1:6379> GEODIST china:city suzhou chongqing km"1423.8065"127.0.0.1:6379> GEODIST china:city shzhou shanghai(nil)127.0.0.1:6379> GEODIST china:city shzhou shanghai km(nil)127.0.0.1:6379> GEODIST china:city shzhou shanghai km(nil)127.0.0.1:6379> zrange china:city 0 -1 # 获取所有的元素1) "chongqing"2) "xian"3) "suzhou"4) "shanghai"5) "xingtai"6) "beijing"127.0.0.1:6379> GEODIST china:city suzhou shanghai km"76.9593"## 以给定坐标为中心,给定距离半径内的城市# WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。# WITHCOORD: 将位置元素的经度和维度也一并返回。127.0.0.1:6379> georadius china:city 117.3 40.0 100 km1) "beijing"127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist1) 1) "beijing"2) "85.9885"3) 1) "116.30000084638595581"2) "39.90000009167092543"127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist withcount(error) ERR syntax error127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist Count count(error) ERR value is not an integer or out of range127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist Count(error) ERR syntax error127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist count(error) ERR syntax error127.0.0.1:6379> georadius china:city 117.3 40.0 100 km withcoord withdist1) 1) "beijing"2) "85.9885"3) 1) "116.30000084638595581"2) "39.90000009167092543"## 以给定的元素为中心,给定距离为半径查找127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 100 km1) "beijing"127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km1) "xingtai"2) "beijing"3) "xian"127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km withdist1) 1) "xingtai"2) "352.6012"2) 1) "beijing"2) "0.0000"3) 1) "xian"2) "904.3049"#删除元素; 使用的是zset的api进行删除127.0.0.1:6379> zrem china:city beijing(integer) 1127.0.0.1:6379> zrange china:city 0 -11) "chongqing"2) "xian"3) "suzhou"4) "shanghai"5) "xingtai"
HyperLogLog
统计基数的,{1,2,3,4,5,4,3,2} 基数就是5,因为只有5个互相不通的数.
- 用来统计有效访问人数,重复访问不算.
 - 占的内存固定,比较小
 

127.0.0.1:6379> PFADD mykey a b c d e f g # 添加元素到mykey集合中(integer) 1127.0.0.1:6379> pfcount mykey # 统计基数(integer) 7127.0.0.1:6379> PFADD mykey2 a b c d g h i j # 添加元素到mykey中(integer) 1127.0.0.1:6379> pfcount mykey2 # 统计基数(integer) 8127.0.0.1:6379> PFMERGE mykey3 mykey1 mykey2 # 合并OK127.0.0.1:6379> PFCOUNT mykey3 # 统计基数(integer) 8
Bitmaps
https://www.cnblogs.com/54chensongxia/p/13794391.html
BitMap 原本的含义是用一个比特位来映射某个元素的状态。由于一个比特位只能表示 0 和 1 两种状态,所以 BitMap 能映射的状态有限,但是使用比特位的优势是能大量的节省内存空间。
在 Redis 中,可以把 Bitmaps 想象成一个以比特位为单位的数组,数组的每个单元只能存储0和1,数组的下标在 Bitmaps 中叫做偏移量。
使用场景:
- 用户签到
 - 活跃用户
 - 用户是否在线
 
# 设置值,其中value只能是 0 和 1setbit key offset value# 获取值getbit key offset# 获取指定范围内值为 1 的个数# start 和 end 以字节为单位bitcount key start end# BitMap间的运算# operations 位移操作符,枚举值AND 与运算 &OR 或运算 |XOR 异或 ^NOT 取反 ~# result 计算的结果,会存储在该key中# key1 … keyn 参与运算的key,可以有多个,空格分割,not运算只能一个key# 当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0。返回值是保存到 destkey 的字符串的长度(以字节byte为单位),和输入 key 中最长的字符串长度相等。bitop [operations] [result] [key1] [keyn…]# 返回指定key中第一次出现指定value(0/1)的位置bitpos [key] [value]
事务
- redis单条命令保证原子性,事务不保证原子性
- 事务的原子性是要么一起成功,要么一起失败
 - redis事务中如果其中一个命令错误,那么不会导致后面命令的执行,也不会导致前面命令的回滚
 
 - 事务不会放入一条命令就执行一条命令,而是会在exec之后按顺序执行
 
事务正常流程
- 使用Multi标识开始事务Multi
 - 放入一系列的命令
 - 执行事务Exec
127.0.0.1:6379> MULTI # 开启事务标识OK127.0.0.1:6379> set name zmsQUEUED127.0.0.1:6379> get nameQUEUED127.0.0.1:6379> lpush z1 zmsQUEUED127.0.0.1:6379> lpush z2 zmsQUEUED127.0.0.1:6379> lpop z1QUEUED127.0.0.1:6379> lpop z2QUEUED127.0.0.1:6379> lpop z2QUEUED127.0.0.1:6379> EXEC # 执行事务标识1) OK2) "zms"3) (integer) 14) (integer) 15) "zms"6) "zms"7) (nil)
 
事务失败
127.0.0.1:6379> MULTIOK127.0.0.1:6379> set z zmsQUEUED127.0.0.1:6379> incr z #字符串无法无法+1,失败QUEUED127.0.0.1:6379> set n nameQUEUED127.0.0.1:6379> exec1) OK2) (error) ERR value is not an integer or out of range3) OK127.0.0.1:6379> get n # 依然可以获取失败命令后面的命令执行"name"
取消事务
127.0.0.1:6379> multiOK127.0.0.1:6379> get nameQUEUED127.0.0.1:6379> set name naQUEUED127.0.0.1:6379> DISCARD # 取消事务,放弃已经输入的命令OK
锁
- 悲观锁
- 认为什么时候都会有问题,无论做什么都会加锁.
 
 - 乐观锁
- 认为什么时候都不会出问题,任何时候都不上锁.
 - 更新数据的时候判断一下,在此期间是否有人修改过这个数据,(mysql中是version)
 
 
Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断,事务一旦执行成功,监控自动取消WATCH key ``[``key ``...]
只要监视到其余线程的修改,就取消事务(本线程修改就允许的)
事务正常执行
127.0.0.1:6379> set money 100OK127.0.0.1:6379> set out 0OK127.0.0.1:6379> watch money # 监视moneyOK127.0.0.1:6379> MULTIOK127.0.0.1:6379> INCRBY out 20QUEUED127.0.0.1:6379> DECRBY money 20QUEUED127.0.0.1:6379> exec1) (integer) 202) (integer) 80# 余额跟花费都是正确的
事务失败

先设置money\out并监视
在其他线程修改
事务失败
- 语法错误
 
而只要有一个命令有语法错误,执行EXEC命令后Redis就会直接返回错误,连语法正确的命令也不会执行。
127.0.0.1:6379> multiOK127.0.0.1:6379> set name aQUEUED127.0.0.1:6379> set na # 语法错误(error) ERR wrong number of arguments for 'set' command127.0.0.1:6379> exec # 语法错误事务不执行(error) EXECABORT Transaction discarded because of previous errors.
watch
https://redisbook.readthedocs.io/en/latest/feature/transaction.html 写的很牛逼
WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。监控一直持续到EXEC命令(事务中的命令是在EXEC之后才执行的,所以在MULTI命令后可以修改WATCH监控的键值)
- watch监视后,如果事务执行失败,记得解锁;.
 
整合Java
Jedis
依赖
- jedis
 fastjson ```basic
redis.clients jedis 3.5.1 com.alibaba fastjson 1.2.75 
2. 编码测试1. 连接数据库```basicpublic static void main(String[] args) {// 1. new JedisJedis jedis = new Jedis("localhost", 6379);System.out.println(jedis.ping());Jedis.close();}
- 操作命令
 - 断开连接
 
配置文件Redis.conf
**/opt/redis/zmsconfig**
持久化
Redis是内存数据库,如果不讲内存中的数据库状态保存到磁盘,那么一旦服务器退出,服务器中的数据库状态也会消失,所以Redis提供了持久化的功能.
