Redis基础总结
Redis基础总结
概述
- Redis是什么
Redis(Remote Dictionary Server远程字典服务)
开源的、使用ANSI C语言编写、支持网络、可基于内存、可持久化、Key-Value数据库,提供多种语言的API。
-
为什么用Redis
1、内存存储、持久化,内存中断电即失,(RDB、AOF)
2、效率高、可用于高速缓存
3、发布订阅系统
4、地图信息分析
5、计时器、计数器
Windows 安装
github中下载安装
Linux安装
-
官网下载安装包 , 解压
tar -xvf redis-6.2.6.tar.gz
-
安装gcc环境并编译
yum -y install gcc automake autoconf libtool make yum install gcc gcc-c++ cd /opt/redis-6.2.6 make make install
-
修改redis.conf并启动服务
daemonize yes #conf中设置后台启动 redis-server redisconf/redis.conf 启动服务 redis-cli -p 6379 客户端连接测试
Redis 基础
-
redis有16个数据库
select 3 选择数据库 dbsize 查看数据库大小 keys * 查看所有key flushall flushdb 清除数据
-
Redis是单线程的
基于内存操作,CPU不是redis性能瓶颈,性能由机器内存和网络带宽决定,
为什么不是多线程? 防止CPU上下文切换
基本命令
set name tangtang
get name
exists name #是否存在,存在1,不存在0
move name 1 #移动name到数据库1
expire name 10 #设置过期时间10秒
ttl name #查看剩余过期时间
type name #查看key类型
Redis命令中的区间都是【0,3】,闭合区间
String
append name meme #追加
strlen #查看长度
incr views #view值自增,相当于view++
decr views #view值自减,相当于view--
incrby views 10 #增加10,相当于view+=10
getrange name 0 3 #获取截取字符串,相当于view.substring(0,4)
setrange name 1 tt #修改字符串,相当于replace
setex name 10 #设置10秒后过期
setnx name tangtangtang #不存在则设置
mset k1 v1 k2 v2 #批量设置key
mget k1 k2 #批量获取
msetnx k1 v1 k4 v4 #原子性操作,key不存在时批量设置
getset db redis #先get再set
del name #移除key
使用场景: 计数器、统计数
List
lpush list one two #在头部添加,返回数量
rpush list right #在尾部添加,返回数量
lpop list #从头部抛出,返回抛出值
rpop list #从尾部抛出,返回抛出值
lrange list 0 -1 #查看list所有值
lindex list 0 #查看第一个值
llen list #查看长度
lrem list 2 three #从头部移除两个three值 ,count>0从前往后移除,=0移除全部,<0从后往前
ltrim list 1 2 #截取list
rpoplpush list1 list2 #右抛出左压入
lset list 0 val #将list指定下标值替换成新的值,前提list存在
linsert list after "么么" "哒" #向指定值的前后插入(linsert key before|after val insVal)
- 双向链表,在两边插入或改动值效率高,
- 用作消息队列、栈
Set
sadd set one #添加值
smembers set #查看所有
sismember set one #查看one是否存在集合里,存在返回1,不存在返回0
scard set #查看数量
srem set one #移除指定元素
srandomember set #随机抽取一个元素
srandomember set 2 #随机抽两个元素
spop set 2 #随机取出并删除两个元素,返回
smove myset myset2 lala #从myset移到myset2
sdiff key1 key2 #返回key1-交集
sinter key1 key2 #返回交集
sunion key1 key2 #返回并集
- Set不可重复
- 应用场景:共同关注,共同好友
Hash
hset myhash key1 tangtang #添加一个myhash, 一个元素key1-tangtang
hget myhash key1 #取key1
hmset myhash key1 tangtang key2 xuxu # 批量添加
hmget key1 key2 # 批量获取
hgetall myhash # 获取全部
hdel myhash key1 key2 # 删除两个key
hlen myhash # 查看数量
hexists myhash key1 # 查看myhash中是否有key1
hkeys myhash # 返回所有key
hvals myhash # 返回所有value
hincrby myhash key3 1 # myhash中key3的值增加1,hdecrby同理
hsetnx myhash key3 100 # key3不存在则新增,返回1成功,0失败
- Map集合,key-map1
- 应用场景: 用户信息存储、
ZSet
zadd myzset 1 one 2 two #添加两个值
zrange myzset 0 -1 #查看所有
zrangebyscore myzset -inf +inf withscores #查看所有,带上score值
zrevrange myzset 0 100 [withscores] #按score倒序查询[0,100]之间的元素
zrem myzset one1 #移除one1
zcard myzset #查看数量
zcount myzset 1 (2 #获取score在[1,2)的元素
- 有序集合,在set基础上增加一个score值
- 应用场景:排行榜、工资表排序、带权重
特殊数据类型
-
Geospatial 地理位置
geoadd china:city 116.40 39.90 beijing # key必须是两级 geoadd 经度 纬度 pos geopos china:city beijing #获取指定的pos经度和纬度 geodist china:city beijing hangzhou km #获取两地理位置的距离 georadius china:city 100 30 1000 km withdist withcoord #获取某地理位置1000km半径的地理位置 1) 1) "Palermo" 2) "190.4424" 3) 1) "13.361389338970184" 2) "38.115556395496299" 2) 1) "Catania" 2) "56.4413" 3) 1) "15.087267458438873" 2) "37.50266842333162" georadiusbymember china:city bejing 1000 km #获取元素1000km半径内的元素
-
Redis 3.2版本推出
-
应用场景: 附近的人、打车距离计算
-
-
HyperLogLog
pfadd key a b c e #添加元素 pfcount key #查询数量 pfmerge key1 key2 key3 #取key1和key2的并集到key3中
- 底层Zset , 无序不重复集合
- 应用场景: 浏览量统计
-
BitMap
setbit sign 0 1 # 添加key的0元素为1 bitcount sign #获取key元素为1的数量
- 位图、位存储、只有0 1、
- 应用场景: 统计用户信息、打卡记录、登录状态
Redis事务
本质:一组命令的集合,事务中的命令会被序列化, 放进队列中顺序执行
特性:一次性、顺序性、排他性
Redis没有隔离级别的概念,所有命令在事务中不是直接执行,只有在发起执行命令时才会执行。
Redis单个命令保证原子性、但事务不保证原子性
顺序:开启事务(multi)、命令入队(—)、执行事务(exec)[取消事务(discard)]
异常:编译时异常(命令编译错误,所有命令都不执行)、运行时异常(命令存在语法问题,执行失败,错误命令抛出异常,其他命令正常执行)
multi
set num 10
...
discard / exec
Redis乐观锁
watch num
multi
incrby num 10
get num
exec
# 如果执行EXEC 或者DISCARD, 则不需要手动执行UNWATCH 。
## 如果事务执行前有其他修改操作,可解锁重新获取
# java中可自旋获取
Jedis
Jedis、官方推荐的java连接开发工具
-
1、导入依赖
<!--jedis包--> <dependencies> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.7.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.58</version> </dependency> </dependencies>
-
2、测试
Jedis jedis = new Jedis("192.168.126.134",6379); Client client = jedis.getClient(); String ping = jedis.ping(); System.out.println(ping);
SpringBoot整合
默认使用Lettuce
-
1、导入starter依赖
-
2、自定义redisTemplate
@Configuration public class RedisConfig { @Bean @SuppressWarnings("all") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate(); template.setConnectionFactory(redisConnectionFactory); //json序列化配置 Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY) ; om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance , ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); serializer.setObjectMapper(om); //string序列化配置 StringRedisSerializer stringSerializer = new StringRedisSerializer(); //key的序列化方式 template.setKeySerializer(stringSerializer); //value的序列化方式 template.setValueSerializer(serializer); //hash key的序列化方式 template.setHashKeySerializer(stringSerializer); //hash value的序列化方式 template.setHashValueSerializer(serializer); //调用初始化方法 template.afterPropertiesSet(); return template; } }
Redis配置
########################网络等#########################
1、指定内存大小
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
2、引入其他配置文件
# include .\path\to\local.conf
# include c:\path\to\other.conf
3、允许访问的地址
bind 127.0.0.1
4、是否开启保护模式, 默认开启
protected-mode yes
5、访问端口
port 6379
########################通用#########################
1、是否以守护进程开启
daemonize no
2、指定pid进程文件
pidfile /var/run/redis.pid
3、日志级别,默认生产环境notice
loglevel notice
4、日志文件名
logfile ""
5、数据库数量
databases 16
########################快照RDB#########################
1、持久化规则
save 900 1 #900s内至少有一个key进行了修改就执行持久化
save 300 10 #300s内至少有10个key进行了修改,就执行持久化
save 60 10000 #60s内至少10000个key进行了修改,就执行持久化
2、持久化失败后redis是否继续工作
stop-writes-on-bgsave-error yes
3、是否压缩持久化rdb文件,需消耗cpu资源
rdbcompression yes
4、是否校验rdb文件
rdbchecksum yes
5、rdb文件保存目录
dir ./
########################安全#########################
1、设置密码
requirepass 123456
127.0.0.1:6379> config set requirepass 123456 #命令修改,重启后失效
########################限制#########################
1、最大连接数
maxclients 10000
2、最大内存容量
maxmemory <bytes>
3、内存到达上线时的处理
maxmemory-policy noeviction
maxmemory-policy 八种方式:
1、volatile-lru:只对设置了过期时间的key进行LRU(默认值)
2、allkeys-lru : 删除LRU算法的key
3、volatile-lfu:只对设置了过期时间的key进行LFU算法进行删除 #2.6+版本
4、allkeys-lfu:对所有key执行LFU算法进行删除 #2.6+版本
6、volatile-random:随机删除即将过期key
6、allkeys-random:随机删除
7、volatile-ttl : 删除即将过期的
8、noeviction : 永不过期,返回错误
#LRU(Least Recently Used),最近最久未使用,Redis采用近似LRU算法,为每个key维护一个时钟,记录访问时间,
#淘汰时选取固定数量的key,淘汰其中最近最久未使用的。
# 3.0版本LRU,维护一个pool,首次选取的key按访问时间戳顺序放入,之后选取的key时间戳必须小于池中最小值,
#满了后新增需取出pool最大的key,淘汰时淘汰最小时间戳的key
#maxmemory_samples #淘汰时样本值,越大越接近真实LRU算法,但消耗也变高,对性能有影响
########################AOF#########################
1、是否开启aof模式
appendonly no
2、aof持久化名字
appendfilename "appendonly.aof"
3、同步
#appendfsync always #每次更新时同步
appendfsync everysec #每秒同步,可能丢失1s数据
#appendfsync no #不执行
4、重写时是否关闭aof同步
no-appendfsync-on-rewrite no
5、重写触发方式,两项都满足的情况
auto-aof-rewrite-percentage 100 #当前aof文件和最后一次重写后的aof文件比率大于100时触发重写
auto-aof-rewrite-min-size 64mb #aof文件大于64mb时触发重写
Redis持久化
RDB (Redis DataBase)
-
什么是RDB?
在指定的时间间隔内将内存中的数据以快照的形式写入磁盘,恢复时将快照文件读取到内存里
-
Redis如何实现RDB?
Redis单独创建一个子进程,遍历Redis中的数据,先将数据写入临时文件中,写完后替换上次持久化的文件
优点:主进程不做任何IO操作,确保性能
-
RDB的优缺点
优点:速度快,适合大规模数据恢复
缺点:需要一定的时间间隔进行操作,可能会丢失最后一次持久化的数据
-
触发机制
- save规则满足的情况下
- 执行flushall命令
- 停止Redis服务
- bgsave命令
AOF (Append Only File)
-
什么是AOF?
在每次执行写入操作的时候,redis创建一个子进程记录命令到内存缓存区aof_buf中,每秒或者每次写入时把命令同步到aof日志中。
-
什么是AOF重写?
当Redis不在进行RDB或AOF操作,并且重写条件满足时,Redis创建子进程 ,对AOF日志进行重写,去除无关命令,生成新AOF日志,并把重写期间增量的AOF日志追加到新的日志中,原子地替换旧日志.(若重写期间断电,不会影响旧日志的写入,保证一致性)
-
触发机制
- bgrewriteaof命令