Redis笔记总结

目录

0,本文主要涉及

1,Redis简介

2,基础数据结构以及API 

1,字符串(String)

2,列表(List)

3,集合(Set)

4,有序集合(Sorted Set)

5,散列(Hash)

6,位图(Bitmap )

7,HyperLogLog

8,地理坐标(GEO)

3,扩展功能

1,连接相关命令

2,与 key相关基础功能

3,过期机制

4,排序功能

5,事务机制

6,发布与订阅

7,Lua 脚本支持

8,慢日志记录

4,持久化机制

1,RDB Snapshotting 快照方式

2,AOF Append-only file 操作日志备份

5,master-slave 机制&Redis Sentinel

1,master-slave 机制&数据同步复制

2,Redis Sentinel

6,更多分布式方案


0,本文主要涉及

Redis简介,基础数据结构以及API,扩展功能(自动过期、pipeline和事务、Lua脚本支持,发布订阅等等),持久化配置以及分布式集群实现,使用经验整理

1,Redis简介

Redis(REmote DIctionary Server) 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API,可以看作是数据结构服务器( Data Structures Server)
Redis(集群)本质:一套分布式抽象结构化内存数据读写系统
Redis的特性:
高性能高并发,单机10wOPS
实现代码简洁,2万多行C语言实现,原生实现了IO多路复用
API客户端支持多种语言平台
多种数据结构,字符串值,列表,集合,哈希等等,详见第二小节
丰富扩展功能,自动过期、pipeline和事务、Lua脚本支持,发布订阅等,详见第三小节
支持数据持久化,支持主从复制,支持实现高可用、分布式,详见第四小节
使用场景:
缓存,分布式锁,分部式id生成器,消息队列等等
好友关系、自动补全、摇一摇、网址缩短器、唯一计数器、排行榜、登录会话记录等等

2,基础数据结构以及API 

Redis最核心功能就是提供了这些基础数据结构以及相应的提供操作的API,这些API设计是都源自于每种数据结构最原生的操作逻辑。

1,字符串(String)

二进制安全,可以存储字符串,也可以存储数值,也可以是任意的二进制数据(byte[]),限定的最大长度(512M)
内部实现为简单动态字符串 sds (Simple Dynamic String),一种记录长度和字符数组的结构
详细API http://www.redis.cn/commands.html#string,常用的有:
最基础的获取和添加:get key,set key value(多种参数支持:XX 已存在则设置,NX不存在则设置,EX 设置过期时间单秒,PX设置过期时间时毫秒)
追加 APPEND key str123
获取并更新getset  key1 1232
批量操作 mget key1 key2 ,mset key1 value1 key2 value2 ,msetnx key1 value1  key2 value2(都不存在则添加)
原子化的数值操作:incr, incrby,incrbyfloat,decr,decrby

2,列表(List)

列表类型 key elements 有序 可重复
内部通过quicklist实现,节点是ziplist(一种节省内存的双向链表结构)的双端列表结构。(数据较少时直接使用ziplist)
详细API http://www.redis.cn/commands.html#list,常用的有:
添加元素 从尾部rpush key value1 value2,从头插入lpush key value1 value2
删除元素 从头取出 lpop key 从尾取出 rpop key; 阻塞版:blpop或brpop key timeout
修剪 ltrim key start end(start 和 end 也可以用负数来表示与表尾的偏移量)
查询长度 llen key 
索引查询元素 lindex key index
获取元素 lrange key start end
修改元素 lset key index newValue
移动元素 RPOPLPUSH mylist1 mylist2,阻塞版BRPOPLPUSHmylist1 mylist2

3,集合(Set)

集合类型 key values 无序 不重复 支持集合操作 最大可以包含(2的 32 次方-1)个元素
内部通过intset或dict实现,数据较少时intset
详细API http://www.redis.cn/commands.html#set,常用的有:
增加元素 sadd key element
删除元素 srem key element
查询集合大小 scard key
判断是否包含元素 SISMEMBER key member
随机获取count个元素srandmember key [count] 
随机获取并删除count个元素 spop key [count]
集合操作sinter(交)sdiff(差) sunion(并)

4,有序集合(Sorted Set)

有序集合类型 key scores values 根据score有序 无重复
内部通过skiplist和dict实现,(数据较少时直接使用ziplist)
详细API http://www.redis.cn/commands.html#sorted_set,常用的有:
增加元素 zadd key score1 element1 score2 element2
删除元素 zrem key elements
删除分值排行一定范围的元素 zremrangebyrank key start end
删除一定分值范围元素 zremrangebyscore key minSxore maxScore
查询集合大小 zcard key
查询元素分值 zscore key element
增加元素分值 zincrby key increScore element
查询一定分值范围元素数量 zcount key minSxore maxScore
获取分值排行一定范围的元素 zrange key start end,倒序版 zrevrange
获取一定分值范围元素 zrangebyscore key minSxore maxScore
查询元素分值排名 zrank ,倒序版 zrevrank,一定分值范围版zrevrangebyscore
集合操作:zinterstore,zunionstore

5,散列(Hash)

哈希类型 key field value
内部通过dict实现,(数据较少时直接使用ziplist)
详细API http://www.redis.cn/commands.html#hash,常用的有:
添加获取删除属性  hset hsetnx hget hgetall hdel 
批量操作 hmget key field1 field2, hmset key field1 value1 field2 value2
判断是否存在属性 hexists key field 
查询属性数量 hlen
获取所有属性 hkeys
获取所有值 hvals key
数值操作 hincr、hdecr、hincrby、hdecrby、HINCRBYFLOAT

6,位图(Bitmap )

实际被归类为字符串类型 最大512MB
常用的API有:
设置值 setbit key offset value
获取值 getbit key offset
统计值为1的个数 bitcount key [start end]
做(交集)、or(并集)、not(非)、xor(异或)操作并将结果保存在destkey中 bitop op destkey key[key..…]
查询第一个偏移量对应的值等于targetBit的位置 bitpos key targetBit[start][end]

7,HyperLogLog

用于基数统计,基于HyperLogLog算法实现,有约0.81%错误率
HyperLogLog算法简要说明
原理:把数据抽象为概率实验,通过结果概率分布估算实验次数(不同数据条数即基数)
具体思路:把输入数据记录通过哈希算法得到01二进制数据串,把二进制数据串每位的0和1看作是一次伯努利实验的结果,截取其中首次出现1的前n位数据看作是一次伯努利过程的记录,并记录n(即第n次实验成功),n=2^k,从而可以算出实验次数k
算法优化:分桶计算(把数据串一部分作为桶index),调和平均,偏差修正
详细API http://www.redis.cn/commands.html#hyperloglog,常用的API有:
添加 pfadd key element[element..] 存在返回 1,否则返回 0
查询基数 pfcount key[key...J:计算hyperloglog的独立总数
合并 pfmerge destkey sourcekey[sourcekey...]

8,地理坐标(GEO)

实际数据类型是是sorted set,通过Geohash实现,可能有0.5%误差
用于GEO(地理信息定位):存储经纬度,计算两地距离,范围计算等
详细API http://www.redis.cn/commands.html#geo,常用的API有:
添加地理位置信息 GEOADD key longitude latitude member [longitude latitude member ...]
删除 用 zset命令zrem key member
获取GEOHash GEOHASH key member [member ...]
获取地理位置 geopos key member[member..…]
获取两个地理位置的距离 geodist key member1 member2[unit]unit:m(米)、km(干米)、mi(英里)、ft(尺)
获取指定坐标范围内的地理位置信息集合 georadius key longitude latitude radiusmlkmlftlmi[withcoord][withdist][withhash][COUNT count][ascldesc][store key][storedist key]
获取指定位置范围内的地理位置信息集合 georadiusbymember key member radiusmlkmlftlmi[withcoord][withdist][withhash][COUNT count][ascldesc][store key][storedist key]
withcoord:返回结果中包含经纬度。
withdist:返回结果中包含距离中心节点位置。
withhash:返回结果中包含geohash COUNT count:指定返回结果的数量。
ascldesc:返回结果按照距离中心节点的距离做升序或者降序。
store key:将返回结果的地理位置信息保存到指定键。
storedist key:将返回结果距离中心节点的距离保存到指定键

3,扩展功能

1,连接相关命令

详细API http://www.redis.cn/commands.html#connection​​​​,常用的API有:
设置验证密码 config set requirepass "mypasswordxxxx"(Redis性能很很强,并且没有防破解限制,所以密码要尽量设置的复杂一些)
验证登录 AUTH mypasswordxxxx
检测服务器是否在运行,或者测试延迟 PING
关闭当前连接 QUIT 当所有等待中的回复都写入客户端后,就会立即关闭当前连接

2,与 key相关基础功能

用于标记一个Redsi中的数据, 二进制安全字符串,有限定的最大长度(512M)
在操作具体操作数据的API中都需要有key作为参数
通用的操作对象是key的API:
TYPE 用于判断key对应数据类型
OBJECT 用来查询key对应数据相关信息,具体用法:OBJECT REFCOUNT key:返回指定 key 的值的引用数量;OBJECT ENCODING key:返回指定 key 的内部存储使用的编码格式;OBJECT IDLETIME key:返回指定 key 的空闲时间(有多长时间没有被读写),目前最小精度为 10 秒,这一命令经常在 Redis 淘汰机制中使用(淘汰策略为 LRU 或 noeviction);OBJECT FREQ key:返回指定 key 访问频率的对数,当淘汰策略为 LFU 时,这一命令会被用到;OBJECT HELP:返回帮助信息
EXISTS key1 key2 用于判断key是否已存在
DEL key1 key2 key3 用于删除对应key的数据,返回成功删除个数,操作时间复杂度与具体数据结构其中数据量有关,尽量避免一次性删除过多复杂数据类型的操作
UNLINK 也用于删除key,时间复杂度为 O (1),会有另一个线程进行内存释放
RENAME/RENAMENX 从命名key,如果不存在RENAME保错,RENAMENX 如果已经存在的话返回 0,成功返回 1
KEYS key* 通过Glob patterns描述符查找key,返回符合规则的key字符串,由于Redis操作执行是单线程的,耗时的keys操作可能会阻塞别的命令执行,所以一般不会再生产环境应用,是个废命令,相同需求通过scan命令实现,Glob patterns描述符规则:?是单个字符的通配符,* 是任意个数的通配符,[ae] 会匹配到 a 或 e,^e 表示不匹配 e,a-c 表示匹配 a 或 b 或 c,特殊符号使用 \ 隔开
scan 0 match key24* count 1000,0是游标,key24*是key描述,1000是一次最多查询的数量,不会像 KEYS 那样阻塞 Redis,每次查询会返回新的游标和结果(可能为空),直到返回游标为0时表示查询完成
DUMP key1 用于序列化指定键存储的值,用 RESTORE 命令反序列化

3,过期机制

Reids提供了惰性删除以及定期删除两种策略删除过期的数据
常用的API有:
EXPIREAT(秒)/PEXPIREAT(毫秒)/EXPIREAT(Unix 时间戳) 为指定的 key 设置存活时间,设置的存活时间为非正数,或者使用 EXPIREAT设置了一个过去的时间,则这个 key 会直接被删除,存活时间会被 DEL,SET,GETSET 和所有的 STORE 命令删除或者覆盖, RENAME 原有 key 的存活时间会赋给新的 key
TOUCH 修改某一个或多个 key 的最后访问时间,如果 key 不存在,则忽略
PERSIST 清除存活时间,使指定的 key 成为一个永久的 key
TTL/PTTL 返回指定 key 的剩余存活时间,TTL单位为秒,PTTL为毫秒,如果 key 不存在,则返回 - 2;如果 key 是永久的,则返回 - 1。

4,排序功能

返回或存储 key 的 list、 set 或 sorted set 中的元素,默认按照数值类型排序的,并且按照两个元素的双精度浮点数类型值进行比较。默认从小到大排序,需要按照字典顺序排序,可以使用 ALPHA 修饰符
详细说明: http://www.redis.cn/commands/sort.html
SORT key [BY pattern] [LIMIT offset count] [GET pattern] [ASC|DESC] [ALPHA] destination

5,事务机制

Redis的事务不支持回滚(roll back),并认为回滚机制在通常情况下, 不能解决编程错误带来的问题
详细说明:http://www.redis.cn/commands.html#transactions
常用的API有:
MULTI 标记事务块的开始,之后的命令被顺序插入缓存队列中
EXEC 执行队列中的全部命令,然后将连接状态置为正常状态。如果某些 key 处于被监视状态,并且队列中有和这些 key 相关的命令。那么 EXEC 命令只有在这些 key 的值没有变化的情况下事务才会执行,否则事务被打断
DISCARD 放弃所有队列中的命令,将连接状态置为正常状态。如果事务被 WATCH,则取消所有的 WATCH
WATCH 将指定的 key 标记为被监视状态,如果事务执行前被改动,则事务会被打断
UNWATCH 清除掉所有被 WATCH 的 key,如果调用了 EXEC 或者 DISCARD 命令,则不用手动调用 UNWATCH 命令

6,发布与订阅

发布者将消息发送给订阅了相应频道的订阅者
详细说明:http://www.redis.cn/commands/pubsub.html
常用的API有:
PUBLISH channel message 将信息 message 发送到指定的频道 channel
SUBSCRIBE channel [channel ...] 订阅给指定频道的信息
PSUBSCRIBE pattern [pattern ...] 订阅符合给定Glob patterns模式频道的信息
UNSUBSCRIBE [channel [channel ...]] 退订给定的频道,若没有指定频道则退订所有频道
PUNSUBSCRIBE [pattern [pattern ...]] 退订符合给定Glob patterns模式频道的信息,若果没有提供模式则退出所有模式。
pubsub channels 列出至少有一个订阅者的频道。
pubsub numsub[channel..] 列出给定频道的订阅者
pubsub numpat 列出被订阅模式的数量

7,Lua 脚本支持

脚本命令具有原子性
详细说明: http://www.redis.cn/commands.html#scripting
常用的API有:
执行脚本 EVAL script numkeys key [key ...] arg [arg ...] 更多说明http://www.redis.cn/commands/eval.html
执行缓存到服务器的脚本 EVALSHA sha1 numkeys key [key ...] arg [arg ...]
将脚本缓存到服务器 SCRIPT LOAD script
检查脚本是否存在缓存 SCRIPT EXISTS script [script ...]
清空 Lua 脚本缓存 SCRIPT FLUSH 

8,慢日志记录

添加慢查询配置
config get slowlog-max-len=128
config get slowlog-log-slower-than=10000
慢查询命令
1.slowlog get[n]:获取慢查询队列信息
2.slowlog len:获取慢查询队列长度
3.slowlog reset:清空慢查询队列
可能的长(慢)命令
keys,flushall,flushdb,slow lua script,mutil/exec,operate big value(collection)
运维使用经验
1.slowlog-max-len不要设置过大,默认10ms,通常设置1ms
2.slowlog-log-slower-than不要设置过小,通常设置1000左右
3.理解命令生命周期
4.定期持久化慢查询

4,持久化机制

1,RDB Snapshotting 快照方式

需要大内存,copy-on-write,不可控丢失数据
命令触发:save 同步阻塞主进程 旧的会被替换,bgsave 主进程会 fork 一个子进程异步程处理 
配置自动触发,太消耗内存一般不使用
1、将存储在内存的数据以快照的方式写入二进制文件中,如默认 dump.rdb 中
2、save 900 1#900 秒内如果超过 1 个 Key 被修改,则启动快照保存
3、save 300 10#300 秒内如果超过 10 个 Key 被修改,则启动快照保存
4、save 60 10000#60 秒内如果超过 10000 个 Key 被修改,则启动快照保存
基本配置
dbfilename dump-${port}.rdb 
dir /bigdiskpath 
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
常用触发配置
关闭默认save配置,全量复制,debug reload,shutdown

2,AOF Append-only file 操作日志备份

服务会将每个收到的写命令通过 write 函数追加到文件中(appendonly.aof)
配置自动触发(一般使用appendfsync everysec配置,每秒保存一次)
appendonly yes #开启 AOF 持久化存储方式
appendfsync always #收到写命令后就立即写入磁盘,IO消耗大,效率最差,效果最好
appendfsync everysec # 每秒写入磁盘一次,效率与效果居中
appendfsync no #完全依赖 OS,效率最佳,效果没法保证
通过AOF 重写可以压缩体积,优化加速恢复
常用AOF重写配置
auto-aof-rewrite-min-size AOF文件重写需要的尺寸
aof current size>auto-aof-rewrite-min-size
auto-aof-rewrite-percentage AOF文件增长率
aof_ current_ size-aof_base_ size/aof_ base_size>auto-aof-rewrite-percentage
基础配置
appendonly yes 
appendfilename "appendonly-$(port). aof"
appendfsync everysec 
dir/bigdiskpath 
no-appendfsync-on-rewrite yes 
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

5,高可用方案 master-slave 机制&Redis Sentinel

基于master-slave机制完成数据同步复制,Redis Sentinel完成主从服务监控、提醒和自动故障转移从而实现分布式下高可用的Redis

1,master-slave 机制&数据同步复制

slave 可以从master复制数据进行同步同步
主从关系设置
命令设置:SLAVEOF host port,SLAVEOF NO ONE
配置设置:slaveof ,slave-read-only yes
原理:
通过内部命令:PSYNC
runid 每个 Redis 服务器都会有一个表明自己身份的 ID
offset(复制偏移量)主从双方都会各自维持一个 offset。Master 成功发送 N 个字节的命令后会将 Master 的 offset 加上 N,Slave 在接收到 N 个字节命令后同样会将 Slave 的 offset 增加 N。Master 和 Slave 如果状态是一致的那么它的的 offset 也应该是一致的。
2 种场景:
1. 从服务器从来第一次和当前主服务器连接,即初次复制,发送 PSYNC ? -1 命令来进行完整同步
2. 从服务器断线后重新和之前连接的主服务器恢复连接,即断线后重复制,根据记录的offset进行部分复制(偏移差距还在复制jiuy缓冲区范围内,否则全量复制)

2,Redis Sentinel

Redis sentinel 负责对 Redis 集群中的主从服务监控、提醒和自动故障转移,Redis 集群负责对外提供相关服务
基本原理:
Sentinel 集群通过指定的配置文件发现 master,对其进行监控,并且会发送 info 指令获取 master 的从节点信息
Sentinel 集群中的节点通过向其监控的主从节点发送 hello 信息(包含 Sentinel 本身的 ip、端口和 id 等内容)来向其他Sentinel 宣告自己的存在
Sentinel 集群通过订阅连接来接收其他 Sentinel 的 hello 信息
Sentinel 集群通过 ping 命令来检查监控的实例状态,如果在指定时间内没有返回,则认为该实例下线(主观下线)
然后Sentinel 会询问同样监视这个master 的其他Sentinel进行询问,看它们是否同意这个主服务器已经进入下线状态
当Sentinel收集到足够多的主观下线投票之后,它会将主服务器判断为客观下线
确认客观下线后,监听这个master 的几个Sentinel会通过Raft算法投票选出领头的Sentinel,将master 节点被标记为 ODOWN 状态(客观下线),并进行故障转移操作
Sentinel 选择新的 master 的原则:首先判断优先级,选择优先级较小的;如果优先级相同,查看复制下标,选择复制数据较多的;如果复制下标也相同,就选择进程 ID 较小的。
领头的Sentinel会获得宕掉的 master 的一份最新配置版本号 (config-epoch),当 failover 执行结束以后,这个版本号将会被用于最新的配置,通过广播形式通知其它 Sentinel,其它的 Sentinel 则更新对应 master 的配置。

6,分布式方案

1,Codis集群 https://github.com/CodisLabs/codis
2,Redis Cluster集群 https://redis.io/topics/cluster-spec

你可能感兴趣的:(JavaWeb,Redis)