Redis是什么?
Redis是一个key-value存储系统,非关系型数据库。(瑞士军刀)
Redis的特性
速度快 (据说可达到每秒10万次读写)
- 持久化
Redis所有数据保存在内存中,对数据的更新将异步地保存在磁盘上,从而可作到断电不丢失数据 - 多种数据结构
Redis提供了五种主要的数据结构
- 字符串
- 哈希
- 列表
- 集合
- 有序集合
- 列表内容
- 支持多种编程语言
- 功能丰富
- 使用简单
- 主从复制
- 高可用、分布式
Redis典型应用场景
- 缓存系统
1.访问app server
2.到redis中查询数据
3.1 如果redis中有,直接返回数据
3.2 如查redis中没有,那么到storage中查询
4.为了下次访问的效率,将storage的数据保存到redis中
5.从storage中返回数据 - 计数器
- 消息队列系统
- 排行榜
- 社交网络
- 实时系统
Redis安装
Linux
- wget http://download.redis.io/releases/redis-3.0.7.tar.gz
- tar -xzf redis-3.0.7.tar.gz //解压缩
- ln -s redis-3.0.7 redis
- cd redis
- make && make install
可执行文件说明
- redis-server Redis服务器
- redis-cli 命令行客户端
- redis-benchmark 性能测试
- redis-check-aof AOF文件修复工具
- redis-check-dump RDB文件检查工具
- redis-sentinel Redis2.8以后用来启动Sentinel服务器
三种启动方法
- 最简启动
直接执行redis-server
验证方法:
- ps -ef | grep redis
- netstat -antpl | grep redis
- redis-cli -h ip -p port ping - 动态参数启动
redis-server –port 6380 - 配置文件启动
redis-server configPath
简单的客户端连接
key = hello
value = world
客户端返回值
常用配置
- daemonize:是否是守护进程(no|yes)建议yes
- port:对外端口号,默认6379
- logfile:系统日志
- dir:工作目录(日志文件及持久化文件的存放目录)
Redis通用命令
一般不在生产环境中使用,由于redis是单线程,如果数据量庞大遍历keys将造成线程阻塞
ttl命令,返回-1代表key存在,并且没有过期时间,返回-2代表key已经不存在了,返回大于0的时候,返回的是几就代表这个key的存在时间还有几秒
几个常用命令的时间复杂度
除非键值规模非常小,否则不建议在生产环境中使用复杂度为O(n)级的命令
数据结构和内部编码
字符串
- 结构和命令
- *value不能大于512MB
- get key #获取key对应的value
- set key value #设置key-value
- del key #删除key-value
- 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
- set key value #不管key是否存在,都设置
- setnx key value #只有key不存在才设置
- set key value xx #只有key存在才设置
- mset和mget 批量操作O(n)
- getset key newvalue #set key newvalue并返回旧的value
- append key value #将value追加到旧的value
- strlen key #返回字符串的长度(注意中文,中文非一个字节)
- incrbyfloat key 3.5 #增加key对应的值 3.5
- getrange key start end #获取字符串指定下标所有的值
例如:key=”hello”,value=”javabest”
getrange hello 0 2
value = “jav” - setrange key index value #设置指定下标所有对应的值
setrange hello 4 p #因为下标是从0开始的,所以这里是将value的第5个字符替换为p,结果如下:
value = “javapest”
- 快速实战
记录网站每个用户个人主页的访问量 #incr userid:pageview(单线程:无竟争)
缓存视频的基本信息(数据源在MySQL中)
//通过视频ID获取视频的基本信息
public VideoInfo get(long id){
//定义一个key使用redisPrefix前缀加上视频ID
String redisKey = redisPrefix + id;
//先从redis中获取视频信息
VideoInfo videoInfo = redis.get(redisKey);
if (videoInfo == null){
videoInfo = mysql.get(id);
if (videoInfo != null){
//序列化
redis.set(redisKey, serialize(videoInfo));
}
}
return videoInfo;
}
哈希
- 特点
- 哈希的value分为两个部分,field和value
- field代表属性,value代表值
- field不能重复但是value可以
- hash vs string
- 相似的API
- API
- hget key field #获取hash key对应的field的value
- hset key field value #设置hash key对应field的value
- hdel key field #删除hash key对应field的value
- hexists key field #判断hash key是否有field
- hlen key #获取hash key field的数量
- hmget,hmset批量获取和批量设置
- hgetall key #返回hash key对应的所有的field和value
- hvals key #返回hash key对应的所有的field的value
- hkeys key #返回hash key对应的所有的field
- hsetnx key field value #设置hash key对应field的value,如果field已经存在,则失败
- hincrby key field intCounter #hash key对应的field自增intCounter
- hincrbyfloat key field floatCounter #hincrby浮点数版
- 通过视频ID获取视频的基本信息
public VideoInfo get(long id){
String redisKey = redisPrefix + id;
Map<String, String> hashMap = redis.hgetAll(redisKey);
VideoInfo viedoInfo = transferMapToVideo(hashMap);
if (videoInfo == null){
videoInfo = mysql.get(id);
if (videoInfo != null){
redis.hmset(redisKey, transferVideoToMap(videoInfo));
}
}
return videoInfo;
}
列表
- 结构
- 特点
- 有序
- 可以重复
- 左右两边插入弹出
API
- rpush key value1 value2 value3…valueN #从列表右端插入N个值
- lpush key value1 value2 value3…valueN #从列表左端插入N个值
- linsert key before|after value newValue #在list批定的值前|后插入newValue
- lpop key #从列表左端弹出一个item
- rpop key #从列表右端弹出一个item
- lrem key count value #根据count值,从列表中删除所有value相等的项
- count > 0,从左到右,删除最多count个value相等的项
- count < 0,从右到左,删除最多Math.abs(count)个value相等的项
- count = 0,删除所有value相等的项
- ltrim key start end #按照索引范围修剪列表
- lrange key start end(包含end) #获取列表指定索引范围所有item
- lindex key index #获取列表指定索引的item
- llen key #获取列表长度
- lset key index newValue #设置列表指定索引值为newValue
- blpop key timeout #lpop阻塞版本,timeout是阻塞超时时间,timeout=0为永远不阻塞
- brpop key timeout #rpop阻塞版本,timeout是阻塞超时时间,timeout=0为永远不阻塞
TIPS
- LRUSH + LPOP = Stack #类似于栈的功能
- LPUSH + RPOP = Queue #队列
- LPUSH + LTRIM = Capped Collection #控制列表大小
- LPUSH + BRPOP = Message Queue #实现消息队列
集合
- 特点
- 无序
- 不可重复
- 支持集合间操作
- API
- sadd key element #向集合key添加element.如果element存在则添加失败
- srem key element #将集合key中的element移除
- scard key #计算集合的大小
- sismember key element #判断element是否在集合key中
- srandmember key count #从集合中随机取出count个元素
- spop key #从集合中随机弹出一个元素
- smembers key #取出集合中的所有元素(小心使用)
- sdiff key1 key2 #差集
- sinter key1 key2 #交集
- sunion key1 key2 #并集
- sdiff|sinter|suion + store destkey #将差集|交集|并集结果保存在destkey中
有序集合
- 特点
- 有序
- 无重复元素
- element+score
- API
- zadd key score element #添加score和element(可以多对添加,其中score是可以重复的,但是element不可重复)
- zrem key element #删除元素
- zscore key element #返回元素的分数
- zincrby key increScore element #增加或减少元素的分数
- zcard key #返回元素的总个数
- zrange key start end [WITHSCORES] #返回指定索引范围内的升序元素[分值]
- zrangebyscore key minScore maxScore [WIRHSCORES] #返回指定分数范围内的升序元素
- zcount key minScore maxScore #返回有序集合内在指定分数范围内的个数
- zremrangebyrank key start end #删除指定排名内的升序元素
今天就先到这里,主要的核心就是redis快是因为它使用纯内存,需要注意的是一次只能运行一条命令,所以要避免在线上使用长命令,如:keys,flushall,flushdb,slow lua script,mutil/exec,operate big value(collection)否则这条单行线就堵车了!!!