参考资料
redis实战 http://redisinaction.com/index.html
redis中文网 http://redis.net.cn/
goredis地址:https://github.com/gomodule/redigo
Redis拥有其他数据库所不具备的数据结构,是内存数据库(这使得Redis的速度非常快),具有远程(这使得Redis可以连接多个客户端和服务器)、持久化(这使得服务器可以在重启之后仍然保持重启之前的数据)和可扩展(通过主从复制和分片)等多个特性,使得用户可以以熟悉的方式来为各种不同的问题构建解决方案。
使用场景
1、配合关系型数据库做高速缓存。
例如:高频词、热点访问的数据,降低数据库IO;分布式架构,做session共享。
2、利用多样的数据类型,存储特定的数据。
例如:最新N个数据——通过list实现按自然时间排序的数据。
排行榜,top N——利用zset(有序集合)
时效性的数据,如手机验证码——expire过期
计数器,秒杀——原子性,自增方法INCR、DECR
去除大量数据中的重复数据——利用set集合
构建队列——利用list集合
发布订阅消息系统——pub/sub模式
5种数据结构类型
1、STRING
(字符串) :包括字节串(byte string),整数,浮点数
GET | 获取存储在给定键中的值 |
SET | 设置存储在给定键中的值 |
DEL | 删除存储在给定键中的值(这个命令可以用于所有类型) |
Redis中的自增命令和自减命令
INCR | INCR key-name ——将键存储的值加上1 |
DECR | DECR key-name ——将键存储的值减去1 |
INCRBY | INCRBY key-name amount ——将键存储的值加上整数amount |
DECRBY | DECRBY key-name amount ——将键存储的值减去整数amount |
INCRBYFLOAT | INCRBYFLOAT key-name amount ——将键存储的值加上浮点数amount ,这个命令在Redis 2.6或以上的版本可用 |
供Redis处理子串和二进制位的命令
APPEND | APPEND key-name value ——将提供的值value 追加到给定键key-name 当前存储的值的末尾 |
GETRANGE | GETRANGE key-name start end ——获取一个由偏移量start 至偏移量end 范围内所有字符组成的子串,包括start 和end 在内 |
SETRANGE | SETRANGE key-name offset value ——将从start 偏移量开始的子串设置为给定value |
GETBIT | GETBIT key-name offset ——将字节串看作是二进制位串(bit string),并返回位串中偏移量为offset 的二进制位的值 |
SETBIT | SETBIT key-name offset value ——将字节串看作是二进制位串,并将位串中偏移量为offset 的二进制位的值设置为value |
BITCOUNT | BITCOUNT key-name [start end] ——统计二进制位串里面值为1的二进制位的数量,如果给定了可选的start 偏移量和end 偏移量,那么只对偏移量指定范围内的二进制位进行统计 |
BITOP | BITOP operation dest-key key-name [key-name ...] ——对一个或多个二进制位串执行包括并(AND )、或(OR )、异或(XOR )、 非(NOT )在内的任意一种按位运算操作(bitwise operation),并将计算得出的结果保存在dest-key 键里面 |
2、LIST
(列表)
RPUSH | RPUSH key-name value [value ...] ——将一个或多个值推入到列表的右端 |
LPUSH | LPUSH key-name value [value ...] ——将一个或多个值推入到列表的左端 |
RPOP | RPOP key-name ——移除并返回列表最右端的元素 |
LPOP | LPOP key-name ——移除并返回列表最左端的元素 |
LINDEX | LINDEX key-name offset ——返回列表中偏移量为offset 的元素 |
LRANGE | LRANGE key-name start end ——返回列表从start 偏移量到end 偏移量范围内的所有元素,包括start 和end |
LTRIM | LTRIM key-name start end ——对列表进行修剪,只保留从start 偏移量到end 偏移量范围内的元素,包括start 和end |
阻塞式的列表弹出命令以及在列表之间移动元素的命令
BLPOP | BLPOP key-name [key-name ...] timeout ——从第一个非空列表中弹出位于最左端的元素,或者在timeout 秒之内阻塞并等待可弹出的元素出现 |
BRPOP | BRPOP key-name [key-name ...] timeout ——从第一个非空列表中弹出位于最右端的元素,或者在timeout 秒之内阻塞并等待可弹出的元素出现 |
RPOPLPUSH | RPOPLPUSH source-key dest-key ——从source-key 列表中弹出位于最右端的元素,然后将这个元素推入到dest-key 列表的最左端,并向用户返回这个元素 |
BRPOPLPUSH | BRPOPLPUSH source-key dest-key timeout ——从source-key 列表中弹出位于最右端的元素,然后将这个元素推入到dest-key 列表的最左端, 并向用户返回这个元素;如果source-key 为空,那么在timeout 秒之内阻塞并等待可弹出的元素出现 |
3、SET
(集合)
SADD | SADD key-name item [item ...] ——将一个或多个元素添加到集合里面,并返回被添加元素当中原本并不存在于集合里面的元素数量 |
SREM | SREM key-name item [item ...] ——从集合里面移除一个或多个元素,并返回被移除元素的数量 |
SISMEMBER | SISMEMBER key-name item ——检查元素item 是否存在于集合key-name 里 |
SCARD | SCARD key-name ——返回集合包含的元素的数量 |
SMEMBERS | SMEMBERS key-name ——返回集合包含的所有元素 |
SRANDMEMBER | SRANDMEMBER key-name [count] ——从集合里面随机地返回一个或多个元素。当count 为正数时,命令返回的随机元素不会重复; 当count 为负数时,命令返回的随机元素可能会出现重复 |
SPOP | SPOP key-name ——从集合里面移除并返回一个随机元素 |
SMOVE | SMOVE source-key dest-key item ——如果集合source-key 包含元素item , 那么从集合source-key 里面移除元素item ,并将元素item 添加到集合dest-key 中; 如果item 被成功移除,那么命令返回1,否则返回0 |
用于组合和处理多个集合的Redis命令
SDIFF | SDIFF key-name [key-name ...] ——返回那些存在于第一个集合、但不存在于其他集合中的元素(数学上的差集运算) |
SDIFFSTORE | SDIFFSTORE dest-key key-name [key-name ...] ——将那些存在于第一个集合、但并不存在于其他集合中的元素(数学上的差集运算)存储到dest-key 中 |
SINTER | SINTER key-name [key-name ...] ——返回那些同时存在于所有集合中的元素(数学上的交集运算) |
SINTERSTORE | SINTERSTORE dest-key key-name [key-name ...] ——将那些同时存在于所有集合的元素(数学上的交集运算)保存到键dest-key |
SUNION | SUNION key-name [key-name ...] ——返回那些至少存在于一个集合中的元素(数学上的并集计算) |
SUNIONSTORE | SUNIONSTORE dest-key key-name [key-name ...] ——将那些至少存在于一个集合中的元素(数学上的并集计算)存储到dest-key 中 |
4、HASH
(散列)
HSET | 在散列里面关联起给定的键值对 |
HGET | 获取指定散列键的值 |
HMGET | HMGET key-name key [key ...] ——从散列里面获取一个或多个键的值 |
HMSET | HMSET key-name key value [key value ...] ——为散列里面的一个或多个键设置值 |
HDEL | HDEL key-name key [key ...] ——删除散列里面的一个或多个键值对,返回成功找到并删除的键值对数量 |
HLEN | HLEN key-name ——返回散列包含的键值对数量 |
HEXISTS | HEXISTS key-name key ——检查给定键是否存在于散列中 |
HKEYS | HKEYS key-name ——获取散列包含的所有键 |
HVALS | HVALS key-name ——获取散列包含的所有值 |
HGETALL | HGETALL key-name ——获取散列包含的所有键值对 |
HINCRBY | HINCRBY key-name key increment ——将键key 保存的值加上整数increment |
HINCRBYFLOAT | HINCRBYFLOAT key-name key increment ——将键key 保存的值加上浮点数increment |
5、ZSET
(有序集合)
ZADD | ZADD key-name score member [score member ...] ——将带有给定分值的成员添加到有序集合里面 |
ZREM | ZREM key-name member [member ...] ——从有序集合里面移除给定的成员,并返回被移除成员的数量 |
ZCARD | ZCARD key-name ——返回有序集合包含的成员数量 |
ZINCRBY | ZINCRBY key-name increment member ——将member 成员的分值加上increment |
ZCOUNT | ZCOUNT key-name min max ——返回分值介于min 和max 之间的成员数量 |
ZRANK | ZRANK key-name member ——返回成员member 在key-name 中的排名 |
ZSCORE | ZSCORE key-name member ——返回成员member 的分值 |
ZRANGE | ZRANGE key-name start stop [WITHSCORES] ——返回有序集合中排名介于start 和stop 之间的成员,如果给定了可选的WITHSCORES 选项,那么命令会将成员的分值也一并返回 |
有序集合的范围型数据获取命令和范围型数据删除命令,以及并集命令和交集命令
ZREVRANK | ZREVRANK key-name member ——返回有序集合里成员member 所处的位置,成员按照分值从大到小排列 |
ZREVRANGE | ZREVRANGE key-name start stop [WITHSCORES] ——返回有序集合给定排名范围内的成员,成员按照分值从大到小排列 |
ZRANGEBYSCORE | ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] ——返回有序集合中,分值介于min 和max 之间的所有成员 |
ZREVRANGEBYSCORE | ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] ——获取有序集合中分值介于min 和max 之间的所有成员,并按照分值从大到小的顺序来返回它们 |
ZREMRANGEBYRANK | ZREMRANGEBYRANK key-name start stop ——移除有序集合中排名介于start 和stop 之间的所有成员 |
ZREMRANGEBYSCORE | ZREMRANGEBYSCORE key-name min max ——移除有序集合中分值介于min 和max 之间的所有成员 |
ZINTERSTORE | ZINTERSTORE dest-key key-count key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] ——对给定的有序集合执行类似于集合的交集运算 |
ZUNIONSTORE | ZUNIONSTORE dest-key key-count key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] ——对给定的有序集合执行类似于集合的并集运算 |
发布与订阅模式
命令 | 用例和描述 |
---|---|
SUBSCRIBE | SUBSCRIBE channel [channel ...] ——订阅给定的一个或多个频道 |
UNSUBSCRIBE | UNSUBSCRIBE [channel [channel ...]] ——退订给定的一个或多个频道,如果执行时没有给定任何频道,那么退订所有频道 |
PUBLISH | PUBLISH channel message ——向给定频道发送消息 |
PSUBSCRIBE | PSUBSCRIBE pattern [pattern ...] ——订阅与给定模式相匹配的所有频道 |
PUNSUBSCRIBE | PUNSUBSCRIBE [pattern [pattern ...]] ——退订给定的模式,如果执行时没有给定任何模式,那么退订所有模式 |
SORT
命令
使用SORT
命令提供的选项可以实现以下功能:根据降序而不是默认的升序来排序元素;将元素看作是数字来进行排序,或者将元素看作是二进制字符串来进行排序(比如排序字符串'110'
和'12'
的结果就跟排序数字110
和12
的结果不一样);使用被排序元素之外的其他值作为权重来进行排序,甚至从输入的列表、集合或者有序集合那里获取外部值等等。
//如果不加STORE list1,则返回一个排序后的列表,list1不改变。也可储存到其他列表名中
re,err = conn.Do("SORT","list1","STORE","list1")
errCheck(err)
fmt.Println(re) //返回列表长度
事务
Redis是单线程队列式地执行所有客户端发过来的命令,Redis的基本事务(basic transaction)使用MULTI
命令和EXEC
命令,让一个客户端在不被其他客户端打断的情况下执行多个命令。和关系数据库那种可以在执行的过程中进行回滚(rollback)的事务不同,在Redis里面,被MULTI
命令和EXEC
命令包围的所有命令会作为一个整体按顺序执行。当一个事务执行完毕之后,Redis才会处理其他客户端的命令。
REDIS事务分组队阶段和执行阶段,MULTI
命令和EXEC
命令之间是组队阶段,EXEC命令之后是执行阶段。一个事务不具有原子性,即如果一个事务组队完毕,在执行阶段出错,不会整体回滚,错误命令前后的正确的命令会执行。在组队阶段出错,EXEC命令之前如果命令出现错误,事务整体失效,且再执行EXEC命令会报错。
组队过程中,可通过DISCARD命令撤销组队,且事务中所有命令失效,再执行EXEC命令会报错。
用户在事务前使用WATCH key [key...]命令对键进行监视之后,直到执行EXEC命令的这段时间里,如果有其他客户端抢先对任何被监视的键进行了替换、更新删除等操作(及时新值与旧值相等),该用户在尝试执行EXEC命令时,事务将失败并返回错误。UNWATCH命令取消所有监控。如果事务成功执行,在执行EXEC命令时会自动取消所有监控。
键的过期操作
PERSIST | PERSIST key-name ——移除键的过期时间 |
TTL | TTL key-name ——返回给定键距离过期还有多少秒 |
EXPIRE | EXPIRE key-name seconds ——让键key-name 在给定的seconds 秒之后过期 |
EXPIREAT | EXPIREAT key-name timestamp ——将给定键的过期时间设置为给定的UNIX时间戳 |
PTTL | PTTL key-name ——返回给定键距离过期时间还有多少毫秒,这个命令在Redis 2.6或以上版本可用 |
PEXPIRE | PEXPIRE key-name milliseconds ——让键key-name 在milliseconds 毫秒之后过期,这个命令在Redis 2.6或以上版本可用 |
PEXPIREAT | PEXPIREAT key-name timestamp-milliseconds ——将一个毫秒级精度的UNIX时间戳设置为给定键的过期时间,这个命令在Redis 2.6或以上版本可用 |
REDIS持久化
两种方法:RDB(redis database)、AOF(append of file)
两个方法同时启用的话,系统默认采用AOF文件,此时RDB文件可以辅助判断AOF文件是否有误。
用哪个好:1、官方推荐两个都启用;2、如果对数据不敏感,可以单独用RDB;3、不建议单独用AOF,因为可能会出现BUG;4、如果只是做纯内存缓存,可以都不用
REDIS主从复制和集群
主从复制和集群参考 https://blog.csdn.net/sinat_26682309/article/details/89197931
goredis对redis的基本操作
//基本操作
func main() {
conn,err :=redis.Dial("tcp","127.0.0.1:6379")
defer conn.Close()
errCheck(err)
re,err:= conn.Do("SET","key1","val1")
errCheck(err)
fmt.Println(re)
re,err = redis.String(conn.Do("GET","key1"))
errCheck(err)
fmt.Println(re)
re,err = conn.Do("LPUSH","list1","listval")
errCheck(err)
fmt.Println(re)
re,err = redis.Strings(conn.Do("LRANGE","list1",0,-1))
errCheck(err)
fmt.Println(re)
}
//排序
//如果不加STORE list1,则返回一个排序后的列表,list1不改变。如果STORE到其他列表名中,list1不改变
re,err = conn.Do("SORT","list1","STORE","list1") //返回列表长度
//3秒后list1过期,数据清空
re,err = conn.Do("EXPIRE","list1",3)
//list1距离过期还有几秒
re,err = conn.Do("TTL","list1")
//pipline操作
c.Send("SET", "foo", "bar")
c.Send("GET", "foo")
c.Flush()
c.Receive() // reply from SET
v, err = c.Receive() // reply from GET
//pipline事务操作
c.Send("MULTI")
c.Send("INCR", "foo")
c.Send("INCR", "bar")
r, err := c.Do("EXEC")
fmt.Println(r) // prints [1, 1]
//用scan转换多个返回值为go类型
var value1 int
var value2 string
reply, err := redis.Values(c.Do("MGET", "key1", "key2"))
if err != nil {
// handle error
}
if _, err := redis.Scan(reply, &value1, &value2); err != nil {
// handle error
}
实例1:电话验证码
要求:输入电话号码返回4位验证码,有效期1分钟;同一个号码24小时内只能发送3次。
var phoneNo = "1888888" //电话号码
var countKey = phoneNo + ":count" //该电话号码发送次数键名
var codeKey = phoneNo + ":code" //该电话验证码键名
conn,err :=redis.Dial("tcp","127.0.0.1:6379")
errCheck(err)
defer conn.Close()
//获取该电话号码发送验证码次数
count,err := redis.Int(conn.Do("GET",countKey))
errCheck(err)
//对次数判断
//如果超过限制次数
if count > 2 {
fmt.Println("每日只能发送3次")
return
}
//没有超过限制次数
//如果是第一次,设置24小时计数清零
if count == 0 {
_,err := conn.Do("EXPIRE",countKey,60*60*24)
errCheck(err)
}
//生成验证码
rand.Seed(time.Now().Unix())
var code = strconv.Itoa(rand.Int())[:4]
//在缓存数据库中增加验证码
_,err = conn.Do("SET",codeKey,code)
errCheck(err)
_,err = conn.Do("EXPIRE",codeKey,60)
errCheck(err)
//累加验证码发送次数
count,err = redis.Int(conn.Do("INCR",countKey))
errCheck(err)
//返回成功的消息
fmt.Println("发送成功"+strconv.Itoa(count)+"次。"+"验证码为:"+code)