1、查看命中率
登录客户端:info命令
keyspace_hits:159933366
keyspace_misses:2421003
命中率:keyspace_hits/(keyspace_hits + keyspace_misses)
2、分布式锁 setnx
不存在,返回1;存在,返回0;
// 防重处理
Long exists = JedisClientManager.setnx(custLevel + partyIdField.getValue(), partyIdField.getValue(),DateUtil.getTimeOut(TIME_OUT));、
参见 https://blog.csdn.net/andy86869/article/details/81668355
3、批量删除指定的key(利用用linux的xargs命令,把前一个命令的结果当作后一个命令的参数): ./redis-cli KEYS "ECIF:MEMBER_BIND_PHONE*" | xargs ./redis-cli DEL
4、数据类型 dictEntry, key> sds , value>redisObject>sds
5、应用场景: 缓存,分布式session,分布式锁,incr 全局ID, incr 计数器,incr限流,位操作;读多写少;
6、虚拟空间:用户空间 + 内核空间 一般为3:1; 内核空间可以直接操作物理空间;
进程 上下文的切换: 将cpu的上下文 寄存器,程序计数器 保存到 内核空间;
文件描述符File Descriptor , 内核管理已经打开文件的索引;
7、内存回收
过期策略:定时过期(给每个key,设置TTL,对应一个定时任务);惰性过期(下次访问的时候检查过期);定期过期(固定时间点统一检查需要清理的key)
服务器的全局策略:已经超过设置的空间后的策略;lru,lfu
8、持久化机制
RDB(redis database):默认持久化机制;满足条件生成快照dump.rdb;shutdown服务也会生成dump.rdb;flushall也会生成redb;save 命令也会生成rdb;bgsave 异步生成rdb;
AOF(APPEND ONLY FILE): 推荐每一秒;存的是之前的命令,占用磁盘大;
9、分布式相关
sentinal基于raft协议,选取主节点,再由主节点任务一个redis节点为主节点;提供监控和类似注册中心的功能;
多个master-slave组;怎么分片? a:客户端key取hash,比如jedis api b: 单独一个代理服务 twemproxy 节点动态增加需要手动给配置 c: 一致性哈希 hash环 基于顺时针归属一个redis节点 数据用同样的算法算出位置,引入虚拟节点 解决一致性分布不均,实际采用的虚拟槽slot ,基于CRC16 % 16384算法,增加节点后,重新进行分区数据的管理,不同的redisgroup管理不同的槽slot;
pipeline: 一次性发送多个命令打包,然后一次性返回;通过字节大小8192个字节控制客户端一次发送的数据量;客户端有发送缓冲区,服务端有返回缓冲区;适用场景:对于数据成功性和实时性没那么严格的场景;
分布式锁:获取锁: setnx ,通过过期时间防止死锁;通过requestid,只有获取锁的线程才能释放锁;
释放锁:根据requestid,通过rul脚本,判断释放自己锁的,然后释放;
jedis: 线程不安全;springboot2.0以上默认用的是lettuce;redisson服务提供的分布式锁以及队列更加强大;
10、怎么保证数据化和缓存一致性?
10.1 先更新数据库、再删除缓存;
问题: 数据库成功,缓存失败,导致缓存存的旧内容;
解决方案; 如果删除缓存失败了,可以发送消息到一个中间件,不断地删除,但是这样入侵了业务代码;异步方案,更新数据库,会产生binlog,采用阿里canal服务,删除redis缓存;
10.2 先删除缓存,再更新数据库成功;
问题: 缓存删除成功了,数据库也更新成功;看上去没有一致性问题,是会有多线程并发导致不一致的问题;
线程t1, age=1,update 2, 在线程t1,删除缓存age成功,update之前,另外一个线程t2,读取age发现没有缓存,然后读库为1,然后t1更新库为2,而t2补偿到redis我1,这样又导致缓存和数据库不一致;
解决方案:延时双删 ; del(key); update database; del(key);
11、高并发问题
热点数据发现?1、客户端 只能统计本客户端 2、代理层 3、服务端 jedis.monitor有回调的功能,需要解析命令,消耗redis性能,只能单节点;或者用redis-faina ; 4、机器层面 packetbeat
缓存雪崩:大量热点数据,同时失效,这样并发到数据库中;解决方案:ttl增加random时间;部分数据永不过期;预更新即将过期的;
缓存穿透:同样的key,缓存不存在,数据库不存在; 解决方案: 同样的key 数据库查不到,写个带超时时间的空值到redis;
不同样的key(可能被恶意刷),缓存不存在,数据库不存在; 解决方案: 使用布隆过滤器;a) 离线将数据库初始化到布隆过滤器; b) 布隆过滤器查询 c) 过滤器不存在,直接返回 d) 过滤器存在,cache不存在,从数据库查询 e)数据库返回 f) 如果数据库有新数据,需要增量更新到redis;
布隆过滤器可以解决海量数据查找一个元素;布隆过滤器判断如果存在,元素不一定存在;如果判断不存在,则一定不存在;有一定误差; 布隆过滤器为什么不提供删除的方法?怎么支持删除?
12、redis cluster的搭建
/redis-4.0.11 不支持cluster;/redis-5.0.6 是支持cluster;
M: 2def2ae7c410117b2b154bf317c50770a0cbde24 192.168.1.150:7000
slots:[0-5460] (5461 slots) master
M: b52fdc28bb55ce7bd2d2969fade37ce979e0747f 192.168.1.150:7001
slots:[5461-10922] (5462 slots) master
M: bc52ff6e9ad79a955a1422a50bb47b16abd8749a 192.168.1.150:7002
slots:[10923-16383] (5461 slots) master
S: ad1d0e0bf17c887f6e1568e554c68eaef45bd093 192.168.1.150:7003
replicates 2def2ae7c410117b2b154bf317c50770a0cbde24
S: 12fbf6098f067f50901e2e11f08164a087dc00f4 192.168.1.150:7004
replicates b52fdc28bb55ce7bd2d2969fade37ce979e0747f
S: 2b09068181c44fc66cd1495b320be2bb38428bcd 192.168.1.150:7005
replicates bc52ff6e9ad79a955a1422a50bb47b16abd8749a
Master[0] -> Slots 0 - 5460 7000 7003
Master[1] -> Slots 5461 - 10922 7001 7004
Master[2] -> Slots 10923 - 16383 7002 7005
./redis-cli -p 7000
cluster keyslot liuqian -- 查询key归属哪个槽;
搭建cluster步骤参照 https://www.cnblogs.com/caihuaxing/p/11045143.html
https://blog.csdn.net/u010739551/article/details/80228652
单台docker redis的搭建:1、下载最新镜像;
2、手动在宿主机创建 /home/liuqian/redis/data 和 /home/liuqian/redis/conf/ 目录
3、上传redis.conf文件到 /home/liuqian/redis/conf/ 目录
内容:port 6379
appendonly yes
4、创建启动redis容器的shell create_redis.sh,并赋予执行权限;
内容:port=6379;
docker run -d -ti -p ${port}:${port} -p 1${port}:1${port} -v /home/liuqian/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf:rw -v /home/liuqian/redis/data:/data:rw --restart always --name redis-${port} --sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf;
5、执行 create_redis.sh;