无题
Redis初识
Redis的特性
- 速度快
- 持久化
- 多种数据结构
- 支持多种编辑语言
- 功能丰富
- 简单
- 主从复制
- 高可用,分布式
速度快
数据写在内存(主要原因)
使用C语言编写
- 线程模型为单线程
持久化(断电不丢数据)
Redis所有数据保持在内存中,对数据的更新将异步地保存到磁盘上。
多种数据结构
支持多种编辑语言
Java、PHP、Python、Ruby、Lua、node.js
功能丰富
- 发布订阅
- 事务
- Lua脚本
- pipeline
简单
- 不依赖外部库(like libevent)
- 单线程模型
主从复制
从服务器 → 主服务器
高可用,分布式
Redis-Sentinel(v2.8)支持高可用
Redis-Cluster(v3.0)支持分布式
Redis典型应用场景
- 缓存系统
- 计数器
- 消息队列系统
- 排行榜
- 社交网络
- 实时系统
Redis三种启动方式
最简启动
redis-server
动态参数启动
redis-server —port 6380
配置文件启动
redis-server configPath
三种启动方式比较
- 生成环境选择配置启动
- 单机多实例配置文件可以用端口区分开
Redis客户端连接
Redis客户端返回值
Redis常用配置
Redis API的使用和理解
通用命令和数据结构
通用命令
keys
dbsize
- exists key
- del key [key ..]
- expire key seconds
- type key
keys
keys *
遍历所有key
1 | 127.0.0.1:6379> set hello world |
keys [pattern]
遍历所有key
1 | 127.0.0.1:6379> mset hello world hehe haha php good phe his |
keys命令一般不在生产环境使用
key* 怎么用
- 热备从节点
- scan
dbsize
dbsize
计算key的总数
1 | 127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 k4 v4 |
exists
exists
检查key是否存在
1 | 127.0.0.1:6379> set a b |
del
del
删除指定key-value
1 | 127.0.0.1:6379> set a b |
expire、ttl、 persist
expire key seconds
key在seconds秒后过期
ttl key
查看key剩余的过期时间
persist key
去掉key的过期时间
1 | 127.0.0.1:6379> set hello world |
1 | 127.0.0.1:6379> set hello world |
type
type key
返回key的类型
1 | 127.0.0.1:6379> set a b |
主要返回类型
- string
- hash
- list
- set
- zset
- none
时间复杂度
命令 | 时间复杂度 |
---|---|
keys | O(n) |
dbsize | O(1) |
del | O(1) |
exists | O(1) |
expire | O(1) |
type | O(1) |
数据结构和内部编码
单线程
一次只能执行一条命令
拒绝长/慢命令(keys, flushall, flushdb, slow lua script, mutil/exec, operate big value(collection))
- 其实不是单线程(fysnc file descriptor,close file descriptor)
单线程为什么这么快
- 纯内存(主要原因)
- 非阻塞IO
- 避免线程切换和竞态消耗
字符串
字符串键值结构
key | value |
---|---|
hello | world |
counter | 1 |
bits | 10111101 |
字符串类型
场景
- 缓存
- 计数器
- 分布式锁等
get、set、del
get key
获取key对应的value
set key value
设置key-value
del key
删除key-value
1 | 127.0.0.1:6379> set hello world |
incr、decr、 incrby、 decrby
incr key
key自增1,如果key不存在,自增后get(key)=1
decr key
key自减1,如果key不存在,自减后get(key)=-1
incrby key k
key自增k,如果key不存在,自增后get(key)=k
decr key k
key自减k,如果key不存在,自减后get(key)=-k
1 | 127.0.0.1:6379> get counter |
实战
记录网站每个用户个人主页的访问量
incr userid:pageview (单线程 : 无竞争)
缓存视频的基本信息(数据源在MySQL中)伪代码
1 | public VideoInfo get(long id) { |
分布式id生成器
incr id(原子操作)
set、set、setxx
set key value
不管key是否存在,都设置
setnx key value
key不存在,才设置
set key value XX
key存在,才设置
1 | 127.0.0.1:6379> exists php |
mget、mset
mget key1 key2 key3…
批量获取key,原子操作
mset key1 value1 key2 value2 key3 value3
批量设置key-value
1 | 127.0.0.1:6379> mset hello world java best php good |
getset、append、strlen
getset key newvalue
set key newvalue并返回旧的value
append key value
将value追加到旧的value
strlen key
返回字符串的长度(注意中文)
1 | 127.0.0.1:6379> set hello world |
incrbyfloat、getrange、setrange
incrbyfloat key 3.5
加key对应的值3.5
getrange key start end
获取字符串指定下标所有的值
setrange key index value
设置指定下标所有对应的值
1 | 127.0.0.1:6379> incr counter |
总结
命令 | 含义 | 复杂度 |
---|---|---|
set key value | 设置key-value | O(1) |
get key | 获取key-value | O(1) |
del key | 删除key-value | O(1) |
setxn setxx | 根据key是否存在 | O(1) |
Incr decr | 计数 | O(1) |
mget mset | 批量操作key-value | O(n) |
hash
哈希键值结构
key field value
API
hget、hset、hdel
hget key field
获取hash key对应的field的value
hset key field value
设置hash key对应field的value
hdel key field
删除hash key对应field的value
1 | 127.0.0.1:6379> hset user:1:info age 23 |
hexists、hlen
hexists key field
判断hash key是否有field
hlen key
获取hash key field的数量
1 | 127.0.0.1:6379> hgetall user:1:info |
hmget、hmset
hmget key field1 field2…. fieldN
批量获取hash key的一批field对应的值
hmset key field1 value1 field2 value…fieldN valueN
批量设置hash key的一批field value
1 | 127.0.0.1:6379> hmset user:2:info age 30 name kaka page 50 |
hgetall、hvals、hkeys
hgetall key
返回hash key对应所有的field和value
hvals key
返回hash key对应所有field的value
hkeys key
返回hash key对应所有field
1 | 127.0.0.1:6379> hgetall user:2:info |
hsetnx、hincrby、 hincrbyfloat
hsetnx key field value
设置hash key对应field的value(如field已经存在,则失败)
hincrby key field intCounter
hash key对应的field的value自增intCounter
hincrbyfloat key field floatCounter
hincrby浮点数版
实战
记录网站每个用户个人主页的访问量
hincrby user:1:info pageview count
缓存视频的基本信息(数据源在mysql中)伪代码
1 | public VideoInfo get(long id) { |
总结
命令 | 复杂度 |
---|---|
hget set hdel | O(1) |
hexists | O(1) |
hincrby | O(1) |
hgetall hvals hkeys | O(n) |
hmget hmset | O(n) |
List
列表结构
key elements
有序、可重复、左右两边插入弹出
API
rpush、lpush、Linsert
rpush key value1 value2.alueN
从列表右端插入值(1-N个)
lpush key value1 value2.alueN
从列表左端插入值(1-N个)
linsert key before|after value newValue
在list指定的值前|后插入newValue
rpop、lpop、lrem、ltrim
rpop key
从列表右侧弹出一个item
lpop key
从列表左侧弹出一个item
lrem key count value
根据count值,从列表中删除所有value相等的项
(1) count>0 ,从左到右,删除最多count个value相等的项
(2) count<0 ,从右到左,删除最多Math.abs(count)个value相等的项
(3) count=0 , 删除所有value相等的项
Itrim key start end
按照索引范围修剪列表
lrange、lindex、llen
lrange key start end (包含end)
获取列表指定索引范围所有item
lindex key index
获取列表指定索引的item
llen key
获取列表长度
lset
Iset key index newValue
设置列表指定索引值为newValue
1 | 127.0.0.1:6379> rpush mylist a b c |
补充
blpop、brpop
blpop key timeout
lpop阻塞版本,timeout是阻塞超时时间,timeout=0为永远不阻塞
brpop key timeout
rpop阻塞版本,timeout是阻塞超时时间,timeout=0为永远不阻塞
集合
集合结构
key values
无序、无重复、集合间操作
API
sadd、srem
sadd key element
向集合key添加element(如果element已经存在,添加失败)
srem key element
将集合key中的element移除掉
scard、sismember、srandmember、smembers
scard user:1:follow = 4 #计算集合大小
sismember user:1:follow it = 1(存在) #判断it是否在集合中
srandmember user:1:follow count= his #从集合中随机挑count个元素
spop user:1:follow = sports #从集合中随机弹出一个元素
smembers user:1:follow = music his sports it #获取集合所有元素
1 | 127.0.0.1:6379> sadd user:1:follow it news his sports |
sdiff、sinter、sunion
sdiff user:1:follow user:2:follow = music his #差集
sinter user:1:follow user:2:follow = it sports #交集
sunion user:1:follow user:2:follow = it music his sports news ent #并集
sdiff|sinter|suion + store destkey .. #将差集、交集、并集结果保存在destkey中
有序集合
有序集合结构
key score value
集合 | 有序集合 |
---|---|
无重复元素 | 无重复元素 |
无序 | 有序 |
element | element+score |
列表 | 有序集合 |
---|---|
可以重复元素 | 无重复元素 |
有序 | 有序 |
element | element+score |
API
zadd
zadd key score element(可以是多对)
添加score和element
zrem
zrem key element(可以是多个)
删除元素
zscore
zscore key element
返回元素的分数
zincrby
zincrby key increScore element
增加或减少元素的分数
zcard
zcard key
返回元素的总个数
1 | 127.0.0.1:6379> zadd player:rank 100 ronaldo 900 messi 800 c-ronaldo 600 kaka |
zrange、zrangebyscore、zcount
zrange key start end [WITHSCORES]
返回指定索引范围内的升序元素[分值]
zrangebyscore key minScore maxScore[WITHSCORES]
返回指定分数范围内的升序元素[分值]
zcount key minScore maxScore
返回有序集合内在指定分数范围内的个数
zremrangebyrank、zremrangebyscore
zremrangebyrank key start end
删除指定排名内的升序元素
zremrangebyscore key minScore maxScore
删除指定分数内的升序元素
1 | 127.0.0.1:6379> zadd player:rank 1000 ronaldo 900 messi 800 c-ronaldo 600 kaka |
总结
操作类型 | 命令 |
---|---|
基本操作 | zadd zrem zcard zincrby zscore |
范围操作 | zrange zrangebyscore zcount zremrangebyrank |
集合操作 | zunionstore zinterstore |
Jedis
Maven依赖
1 | <dependency> |
Jedis直连
生成一个Jedis对象, 这个对象负责和指定Redis节点进行通信
Jedis jedis = new Jedis(“127.0.0.1”, 6379);
jedis执行set操作
jedis. set(“hello”, “world”);
jedis执行get操作,value= “world”
String value = jedis.get(“hello”);
Jedis(String host, int port, int connectionTimeout, int so Timeout)
- host : Redis节点的所在机器的IP
- port : Redis节点的端口
- connectionTimeout : 客户端连接超时
- soTimeou : 客户端读写超时