Redis入门

开始

Redis是一个高性能的key-value 数据库,同时支持list,set,zset,hash等数据结构的存储

第一个尝试:

(先用windows 版本看下入个门,一般linux用的多,学习来源菜鸟教程)

下载安装到一个你能找到的地方

推荐在某个盘下建一个tool的文件夹,把go啦java啦mysql啦Redis啦,这种工具性的工具放进去

https://github.com/tporadowski/redis/releases

下载zip版本

(前提,每个命令提示符都要先进入redis那个文件下,要不找不到,切换路径的命令:cd /d 路径

  1. 在cmd(命令提示符中)打开服务端命令: redis-server.exe redis.windows.conf
    Redis入门_第1张图片

  2. 再开一个命令提示符,开客服端:redis-cli.exe -h 127.0.0.1 -p 6379

  3. 设置键值对:set heiKey ha

  4. 取键值对:get heiKey

Redis入门_第2张图片

数据类型

  • string
  • hash
  • list
  • set
  • zset (有序集合)
简介

偷一张网络视频的图

Redis入门_第3张图片

他是一种nosql数据库,

好处就是如图

作为缓存使用,减小io压力

NoSQL非关系型数据库

  • Memcache
  • Redis
  • mongoDB
  • Neo4j
  • Apache Cassandra
分类 Examples举例 典型应用场景 数据模型 优点 缺点
键值(key-value) Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB 内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。 Key 指向 Value 的键值对,通常用hash table来实现 查找速度快 数据无结构化,通常只被当作字符串或者二进制数据
列存储数据库 Cassandra, HBase, Riak 分布式的文件系统 以列簇式存储,将同一列数据存在一起 查找速度快,可扩展性强,更容易进行分布式扩展 功能相对局限
文档型数据库 CouchDB, MongoDb Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容) Key-Value对应的键值对,Value为结构化数据 数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构 查询性能不高,而且缺乏统一的查询语法。
图形(Graph)数据库 Neo4J, InfoGrid, Infinite Graph 社交网络,推荐系统等。专注于构建关系图谱 图结构 利用图结构相关算法。比如最短路径寻址,N度关系查找等 很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。

linux版本学习

注意事项

xftp连接云服务器的实例主机密码就是root账户密码:W…….


下载安装

下载安装redis

稳定版本安装地址 : https://redis.io/download/#redis-downloads

Redis入门_第4张图片

在linux中安装redis需要有c语言编译环境,centos7,有gcc就行,通过命令检测是否有gcc,

  1. gcc --version检查是否有gcc环境,有的话就
  2. 解压tar -zxvf 压缩包名字
  3. 进入redis文件夹
  4. make把redis编译成c文件
  5. make install安装

我在这里遇到过一个问题,原因是下错了版本,下载成了stack版本,当时没注意…

redis目录简介
Redis入门_第5张图片

启动redis(第一个例子)
  1. 推荐后台启动redis,所以需要,进入到redis目录下,cp redis.conf /etc/redis.conf复制到的目录可以任意(自己知道就行)

  2. 把后台启动改成允许,daemonize no 改成yes,在etc目录下vi redis.conf

  3. /daem搜索一下daemonize no在哪里,vi(vim)命令可别忘了,然后i进入编辑模式,把no改成yes,:wq保存退出

  4. /usr/local/bin目录下后台启动/etc里边的redis.conf,命令:redis-server /etc/redis.conf

  5. redis-cli连接上redis

  6. 欸嘿!第一个例子

    [root@jingZhi bin]# redis-cli
    127.0.0.1:6379> set heiKey ha
    OK
    127.0.0.1:6379> get heiKey
    "ha"
    127.0.0.1:6379> ping
    PONG
    
  7. 关闭redis的后台命令:shutdown然后exit,
    说一下我遇到的问题,第二次,先是关不掉,因为我查看进程发现redis还在后天运行,但是哈,之后直接把我服务器给关了,
    shutdown是直接把电源关了,就是退出和linux系统的连接了,需要在阿里云管理平台开启服务器
    总之就是关闭后台redis这个我暂时没解决,就是关不掉后台
    所以就exit退出这个端口号就行了,让他一直在后端运行吧

  8. 查看进程ps -ef | grep redis

redis来源:Merz

redis介绍
  • 默认16个数据库,默认使用0数据库
  • select 1切换到1数据库

五大数据类型

key键操作
  • 这不是数据类型

使用

  • set key value设置key-value

  • 取出值get key

key键常用命令

  • keys *查看当前库所有key,匹配keys*1
  • exists key判断某个key是否存在
  • type key查看key(的值)类型
  • del key删除指定key
  • unlink key根据value选择非阻塞删除
    表面上先删除,真正的删除在后续异步操作
  • expire key 20设置指定key20秒后过期
  • ttl key查看key还有多少秒过期,-1永远不过期,-2已经过期
  • select 3选择数据库3,默认是0,redis有16个库
  • dbsize查看有多少个key
  • flushdb删除当前库所有key
  • flushall删除所有库所有key,不常用
127.0.0.1:6379> set HeiKey ha
OK
127.0.0.1:6379> set qieKey xi
OK
127.0.0.1:6379> keys *
1) "qieKey"
2) "HeiKey"
127.0.0.1:6379> exists k1
(integer) 0
127.0.0.1:6379> exists qieKey
(integer) 1
127.0.0.1:6379> type HeiKey
string
127.0.0.1:6379> del qieKey
(integer) 1
127.0.0.1:6379> keys *
1) "HeiKey"
127.0.0.1:6379> set naKey ni
OK
127.0.0.1:6379> expire HeiKey 20
(integer) 1
127.0.0.1:6379> ttl HeiKey
(integer) 9
127.0.0.1:6379> ttl HeiKey
(integer) -2                   #-2表示已经过期
127.0.0.1:6379> ttl naKey
(integer) -1                   #-1表示永远不过期
127.0.0.1:6379> select 3
OK
127.0.0.1:6379[3]> select 0
OK
127.0.0.1:6379> dbsize
(integer) 1
127.0.0.1:6379> keys *
1) "naKey"
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty array)

String

说明

  • 二进制安全的,string可以包含任何数据,例如图片,视频等
  • value最大长度为512M
  • String数据结构是简单动态字符串(SDS),类似java的arraylist,个人感觉也类似go的切片,
  • 长度小于1M是,动态加倍扩容,超过1M时候,每次+1M

常用命令

  • set keyname value设置
  • get keyname 取值
  • append keyname value追加内容
  • strlen keyname查看key值长度
  • setnx keyname value当key不存在时,设置key值
  • incr keyname对数字值操作+1
  • decr keyname对数字值操作-1
  • incrby keyname n 对数字值操作+n
  • decrby keyname n对数字值操作-n
  • mset k1 v1 k2 v2设置多个值
  • mget k1 k2取出多个值
  • msetnx懂得都懂,有一点说明,一旦有一个存在则设置都失败
  • getrange keyname 0 3范围取值,0代表第一个,以此……
  • setrange keyname 3 覆盖的内容3代表第四个开始覆盖
  • setex keyname n valuename设置一个值,过期时间是n,值是valuename
  • ttl keyname查看keyname过期时间
  • getset keyname valuename设置valuename新值同时查看旧值
  • 这一块内容需要做一个思维脑图,帮助记忆
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set k1 v100
OK
127.0.0.1:6379> set k2 v200
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
127.0.0.1:6379> get k1
"v100"
127.0.0.1:6379> set k1 v1100
OK
127.0.0.1:6379> get k1
"v1100"
127.0.0.1:6379> append k1 abc
(integer) 8
127.0.0.1:6379> get k1
"v1100abc"
127.0.0.1:6379> strlen k1
(integer) 8
127.0.0.1:6379> setnx k1 asdf
(integer) 0
127.0.0.1:6379> setnx k3 v300
(integer) 1
127.0.0.1:6379> set k4 100
OK
127.0.0.1:6379> incr k4
(integer) 101
127.0.0.1:6379> get k4
"101"
127.0.0.1:6379> decr k4
(integer) 100
127.0.0.1:6379> incrby k4 7
(integer) 107
127.0.0.1:6379> decrby k4 8
(integer) 99
127.0.0.1:6379> get k4
"99"
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> mget k1 k2
1) "v1"
2) "v2"
127.0.0.1:6379> msetnx k11 v11 k1 v11
(integer) 0
127.0.0.1:6379> mset k11 v11 k22 v22
OK
127.0.0.1:6379> set name wangdahai
OK
127.0.0.1:6379> get name
"wangdahai"
127.0.0.1:6379> getrange name 0 3
"wang"
127.0.0.1:6379> setrange name 3 heiha
(integer) 9
127.0.0.1:6379> get name
"wanheihai"
127.0.0.1:6379> setex age 20 value30
OK
127.0.0.1:6379> ttl age
(integer) 17
127.0.0.1:6379> get age
"value30"
127.0.0.1:6379> getset name lalalal
"wanheihai"
127.0.0.1:6379> get name
"lalalal"
127.0.0.1:6379> 

List

说明

  • 单键多值
  • 底层是一个双向链表,两端操作方便,中间操作困难
  • 按照插入顺序排序,添加元素到头部或者尾部
  • 顺序放入,逆序取出,感觉有点像入栈,出栈

常用命令

  • lpush/rpush k1 v1 v2 v3设置一key多value
  • lrange keyname 0 -1从左往右取值,0到-1 可以取到所有的值
  • lpop/rpop keyname 从左/右出来一个值,并且删除这个值。
  • rpoplpush k1 k2k1右边吐出1个值放到k2左边,把k1的最右边的放在k2的第一个了,其他的往后推1,
  • lindex k1 1获取下标为2的元素
  • llen keyname获取keyname长度
  • linsert keyname before/after value newvalue在keyname的value前/后插入newvalue
  • lrem keyname n value删除n个从keyname的value左到右,
  • lset keyname n newvalue用newvalue覆盖keyname的下标为n的元素
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379>  lpush k1 v1 v2 v3
(integer) 3
127.0.0.1:6379> lrange k1 0 -1
1) "v3"
2) "v2"
3) "v1"
127.0.0.1:6379> rpush k2 v1 v2 v3
(integer) 3
127.0.0.1:6379> lrange k2 0 -1
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> lpop k1
"v3"
127.0.0.1:6379> lpop k1
"v2"
127.0.0.1:6379> lrange k1 0 -1
1) "v1"
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> lpush k1 v1 v2 v3
(integer) 3
127.0.0.1:6379> rpush k2 v11 v12 v13
(integer) 3
127.0.0.1:6379> rpoplpush k1 k2
"v1"
127.0.0.1:6379> lrange k2 0 -1
1) "v1"
2) "v11"
3) "v12"
4) "v13"
kkk
127.0.0.1:6379> lrange k1 0 -1
1) "v3"
2) "v2"
127.0.0.1:6379> lindex k1 1
"v2"
127.0.0.1:6379> llen k1
(integer) 2
127.0.0.1:6379> linsert k1 before v3 newv3
(integer) 3
127.0.0.1:6379> lrange k1 0 -1
1) "newv3"
2) "v3"
3) "v2"
127.0.0.1:6379> linsert k1 after v3 newv4
(integer) 4
127.0.0.1:6379> lrange k1 0 -1
1) "newv3"
2) "v3"
3) "newv4"
4) "v2"
127.0.0.1:6379> lrem k1 1 v3
(integer) 1
127.0.0.1:6379> lrange k1 0 -1
1) "newv3"
2) "newv4"
3) "v2"
127.0.0.1:6379> lset k1 1 newv33
OK
127.0.0.1:6379> lrange k1 0 -1
1) "newv3"
2) "newv33"
3) "v2"

list数据结构

  • 将链表和ziplist结合起来组成quicklist,就是将多个ziplist使用双向指针穿起来使用
Set

说明:

  • 自动去重,底层是hash表,复杂度0(1),
  • 其他就和List很像了

底层数据结构

  • 字典,dict,字典是哈希表实现的

常用命令:

  • sadd key value1 value2....添加值
  • smembers key取出该集合所有值
  • sismember key value判断key集合是否含有value
  • scard key返回key的元素个数
  • srem k1 v1 v3删除k1集合的v1 v3元素
  • spop k1随机吐出k1集合一个元素,吐出同时删除了
  • srandmember k1 n随机取出n个值,不会从集合删除
  • smove sourcekey destinationkey value把sourcekey中value移到destinationkey
  • sinter k1 k2返回交集
  • sunion k1 k2返回并集
  • sdiff k1 k2返回差集。包含k1不包含k2的
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> sadd k1 v1 v2 v3
(integer) 3
127.0.0.1:6379> smembers k1
1) "v3"
2) "v2"
3) "v1"
127.0.0.1:6379> sismember k1 v2
(integer) 1
127.0.0.1:6379> sismember k1 v4
(integer) 0
127.0.0.1:6379> srem k1 v1 v3
(integer) 2
127.0.0.1:6379> smembers k1
1) "v2"
127.0.0.1:6379> sadd k1 v3 v4
(integer) 2
127.0.0.1:6379> smembers k1
1) "v4"
2) "v3"
3) "v2"
127.0.0.1:6379> spop k1
"v4"
127.0.0.1:6379> spop k1
"v3"
127.0.0.1:6379> sadd k1 v1 v2 v3 v4 v5 v3
(integer) 4
127.0.0.1:6379> smembers k1
1) "v3"
2) "v1"
3) "v2"
4) "v4"
5) "v5"
127.0.0.1:6379> spop k1
"v1"
127.0.0.1:6379> srandmember k1 2 
1) "v3"
2) "v2"
127.0.0.1:6379> scard k1
(integer) 4
127.0.0.1:6379> smembers k1
1) "v4"
2) "v2"
3) "v3"
4) "v5"
127.0.0.1:6379> spop k1 
"v5"
127.0.0.1:6379> smembers k1
1) "v4"
2) "v2"
3) "v3"
127.0.0.1:6379> smembers k1
1) "v4"
2) "v2"
3) "v3"
127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> sadd k2 v21 v23 v24 v25
(integer) 4
127.0.0.1:6379> smove k1 k2 v2
(integer) 1
127.0.0.1:6379> smembers k2
1) "v25"
2) "v21"
3) "v24"
4) "v23"
5) "v2"
127.0.0.1:6379> smembers k1
1) "v4"
2) "v3"
127.0.0.1:6379> sadd k1 v2 v23
(integer) 2
127.0.0.1:6379> sinter k1 k2
1) "v2"
2) "v23"
127.0.0.1:6379> smembers k1
1) "v4"
2) "v2"
3) "v3"
4) "v23"
127.0.0.1:6379> smembers k2
1) "v21"
2) "v25"
3) "v2"
4) "v23"
5) "v24"
127.0.0.1:6379> sunion k1 k2
1) "v25"
2) "v21"
3) "v4"
4) "v2"
5) "v3"
6) "v24"
7) "v23"
127.0.0.1:6379> disff k1 k2
(error) ERR unknown command `disff`, with args beginning with: `k1`, `k2`, 
127.0.0.1:6379> sdiff k1 k2
1) "v4"
2) "v3"

Hash

说明

  • 键值对集合
  • redis的hash是一个string类型的field和value的映射表,hash特别适合用于存储对象
  • 类似java里边的map
  • 两种存储方式,一是IDkey,对映名字,年龄啦什么的,二是id+名字—对应值

数据结构

  • 两种,ziplist,hashtable
  • 当field-value长度较短且个数较少,使用ziplist,否则使用hashtable

常用命令

  • hset key field valuekey集合field键赋值value,例子hset user:1001 name jingzhi

  • hget key field从key集合filed取出value

  • hmset key field1 value1 field2 value2...批量设置hash值

  • hexists key field产看hash表key中,给定field是否存在

  • hkeys key查看key的所有field

  • hvals key查看key所有的value

  • hincrby key field nkey哈希表中field域值增n,n可以是负数

  • hsetnx key field value当且仅当field不存在时候给field值设置为value

127.0.0.1:6379> hset user:1000 id 1
(integer) 1
127.0.0.1:6379> hset user:1000 name jingzhi
(integer) 1
127.0.0.1:6379> hget user:1000 name
"jingzhi"
127.0.0.1:6379> hmset user:1002 id 2 name lisi age 21
OK
127.0.0.1:6379> hexists user:1000
(error) ERR wrong number of arguments for 'hexists' command
127.0.0.1:6379>  hexists user:1000
(error) ERR wrong number of arguments for 'hexists' command
127.0.0.1:6379> hexists user:1000 name
(integer) 1
127.0.0.1:6379> hkeys user:1002
1) "id"
2) "name"
3) "age"
127.0.0.1:6379> hvals user:1002
1) "2"
2) "lisi"
3) "21"
127.0.0.1:6379> hincrby user:1002 age 7
(integer) 28
127.0.0.1:6379> hsetnx user:1002 age 30
(integer) 0
127.0.0.1:6379> hsetnx user:1002 gender 2
(integer) 1
127.0.0.1:6379> hkeys user:1002
1) "id"
2) "name"
3) "age"
4) "gender"

Zset有序集合

说明

  • 有序集合,没有重复元素
  • 和set区别,都关联了一个score,根据评分,按章从低到高排序,成员唯一,评分可以重复
  • 可以根据评分获取一个范围的元素

数据结构

  • 一方面等价于Map给每一个元素value赋予一个权重score,另一方面类似于TreeSet,内部元素按照权重score进行排序,得到每个元素的名次
  • 底层两个数据结构
    • hash,hash的作用就是关联元素value和权重score,保证value的唯一性,
    • 跳跃表,目的在于给value元素排序,根据score范围获取元素列表

常用命令

  • zadd key score1 value1 score2 value2...将一个或者多个value元素以及score添加集合到key
  • range rank 0 -1 withscores查看所有元素及其分数,0和-1代表下标,0到-1是所有
  • zrangebyscore key n m[withscores]从小到大显示,区间是n——m
  • zrevrangebyscore key m n[withscores]从大到小显示,区间是m——n
  • zincrby key n value给元素value添加n分
  • zrem key value删除key集合value元素
  • zcount key n m统计n 到 m区间的元素个数
  • zrank key value查询该value元素在key集合的排名,排名从0开始
127.0.0.1:6379> zadd rank 99 bainiangudu 98 shuimiangeming 96 wenhuakulv 97 wangyuancheng
(integer) 4
127.0.0.1:6379> zrange rank 0 -1
1) "wenhuakulv"
2) "wangyuancheng"
3) "shuimiangeming"
4) "bainiangudu"
127.0.0.1:6379> zrange rank 0 -1 withscores
1) "wenhuakulv"
2) "96"
3) "wangyuancheng"
4) "97"
5) "shuimiangeming"
6) "98"
7) "bainiangudu"
8) "99"
1
127.0.0.1:6379> zrangebyscore rank 97 99
1) "wangyuancheng"
2) "shuimiangeming"
3) "bainiangudu"
127.0.0.1:6379> zrevrangebyscore rank 98 96
1) "shuimiangeming"
2) "wangyuancheng"
3) "wenhuakulv"
127.0.0.1:6379> zincrby rank 9 shuimiangeming
"107"
127.0.0.1:6379> zrem rank wangyuancheng
(integer) 1
127.0.0.1:6379> zcount rank 1 110
(integer) 3
127.0.0.1:6379> zrank rank bainiangudu
(integer) 1
127.0.0.1:6379> zrange rank 0 -1 withscores
1) "wenhuakulv"
2) "96"
3) "bainiangudu"
4) "99"
5) "shuimiangeming"
6) "107"

配置文件(听了一边,没啥好说的)

  • 只支持bytes,不支持bits

订阅发布

  • pub/sub,发布订阅是一种消息通道模式
  • SUBSCRIBE channel1
  • publish channel1 hello
127.0.0.1:6379> SUBSCRIBE channel1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
1) "message"
2) "channel1"
3) "hei"

#另一个会话
127.0.0.1:6379> publish channel1 hei
(integer) 1
127.0.0.1:6379> 

新特性

bitmaps
  • 极大的节约空间,但是适合大量活跃用户,不适用用户少,和僵尸用户多的情况
  • setbit key 对象 偏移量
  • getbit key 对象
  • setbit unique:key 对象 偏移量
  • bitop and unique:users:and:20201104_03 unique:users:20201103 unique:users:20201104
  • and可以换为or表示并集,and表示交集
127.0.0.1:6379>  setbit user:20210101 1 1
(integer) 0
127.0.0.1:6379>  setbit user:20210101 6 1
(integer) 0
127.0.0.1:6379>  setbit user:20210101 11 1
(integer) 0
127.0.0.1:6379>  setbit user:20210101 16 1
(integer) 0
127.0.0.1:6379>  setbit user:20210101 19 1
(integer) 0
127.0.0.1:6379> getbit users:20210101 6
(integer) 0
127.0.0.1:6379> getbit users:20210101 1
(integer) 0
127.0.0.1:6379> getbit user:20210101 1
(integer) 1

127.0.0.1:6379> setbit unique:users:20201104 1 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201104 2 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201104 5 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201104 9 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201103 0 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201103 1 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201103 4 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201103 9 1
(integer) 0
127.0.0.1:6379> bitop and unique:users:and:20201104_03 unique:users:20201103 unique:users:20201104
(integer) 2
HyperLogLog
  • 没几个命令,没有实际运用说实话感觉不出来它存在的意义
  • 基数统计,比如数据集{1,3,5,7,5,7,8},那么基数就是{1,3,5,7,8},基数(不重复元素)为5
  • redis里面每个HyperLogLog键只需要12kB内存,就可以计算接近2^64个不同元素的基数
  • pfadd key 内容添加
  • pfcount key产看基数
  • pfmerge newkey k1 k2把k1,k2合并到newkey
127.0.0.1:6379> pfadd program "java"
(integer) 1
127.0.0.1:6379> pfadd program "c++"
(integer) 1
127.0.0.1:6379> pfadd program "php"
(integer) 1
127.0.0.1:6379> pfadd program "c++"
(integer) 0
127.0.0.1:6379> pfcount program
(integer) 3
(i
127.0.0.1:6379> pfadd k1 "a"
(integer) 1
127.0.0.1:6379> pfmerge k100 k1 program
OK
127.0.0.1:6379> pfcount k100
(integer) 4

Geospatial
  • GEO类型,Geographic地理信息的缩写
  • 经纬度,元素二维坐标
  • m 米 km 千米 mi英里 ft单位为英尺
  • 有效经度-180到180,有效纬度 -85.05112878 到 85.05112878
  • geoadd key 经度 纬度 城市 经度 纬度 城市...添加
  • geopos key 城市获取经纬度
  • geodist key city1 city2 km获取city1到city2的km
  • georadius key 经度 纬度 radius km获取经纬度radius km范围有几个city
127.0.0.1:6379> geoadd china:city 1.23 2.23 shanghai 2.34 3.34 chengdu 1.23456 2.234 beijing 
(integer) 3
127.0.0.1:6379> geopos china:city beijing
1) 1) "1.23455911874771118"
   2) "2.23400057363439686"
127.0.0.1:6379> geodist china:city beijing shanghai km
"0.6743"
127.0.0.1:6379> georadius china:city 110 30 100 km
(empty array)
127.0.0.1:6379> georadius china:city 110 30 1000 km
(empty array)
127.0.0.1:6379> georadius china:city 10 2 10000 km
1) "shanghai"
2) "beijing"
3) "chengdu"

18——20,因为是走go,所以,jedis,用java操作redis我就跳过了

redis事务

使用
  • 单独隔离操作,所有命令都会序列化,按顺序执行,事务在执行的过程中,不会被其他客户端送来的命令所打断
  • 就是串联多个命令,防止别的命令插队
  • multi 开启事务
  • 事务...
  • exec执行事务
  • discard打断事务
127.0.0.1:6379>  multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
3) "v2"
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set a1 v1
QUEUED
127.0.0.1:6379(TX)> discard
OK

#失败情况
#组队阶段错误
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> set k3
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
#exec阶段错误
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> incr k2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
127.0.0.1:6379> 

解决事务冲突思路
  • 理解层次上的
  • 悲观锁
    • 谁用之前先上锁,别的账户就用不了了,用完之后再解锁
  • 乐观锁
    • 不上锁,但是类似有一种版本号,大家都能拿到数据,谁用到了就更新版本,其他用户用之前先匹配版本号一不一样,一样的话就用,不一样的话就更新
  • 举个例子,火车高铁抢票软件,
乐观锁举例
  • watch key
#会话一
127.0.0.1:6379> set balance 100
OK
127.0.0.1:6379>  watch balance
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> incrby balance 19
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 119
#会话二
127.0.0.1:6379> keys *
1) "k2"
2) "balance"
127.0.0.1:6379> watch balance
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> incrby balance 17
QUEUED
127.0.0.1:6379(TX)> exec
(nil)
redis事务三特性
  • 单独的隔离操作
    • 所有的命令被序列化,按顺序执行,不会被其他客户端发送来的命令请求打断
  • 没有隔离级别的概念
    • 队列中的命令没有提交之前都不会被实际执行,因为任何事务提交前都不会被实际执行
  • 不保证原子性
    • 当有一条命令执行失败,其后的命令仍然会被执行,没有回滚

你可能感兴趣的:(数据库,redis,数据库,nosql)