# springbootRedis **Repository Path**: shixianqing/springbootRedis ## Basic Information - **Project Name**: springbootRedis - **Description**: No description available - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-10-29 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # redis应用 ## redis+token实现接口幂等(防重复) ### 实现 - 用户发交易前先获取一个token,并存于redis - 发交易时,将获取到的token放在请求头中与交易报文一并传与后端 - 后端,在拦截器里获取请求头里的token - 后端,判断请求头里的token是否在redis中存在,不存在,可能发生重复交易,存在则把token从redis中删除 - 后端,判断token是否删除成功,防止并发情况(一个请求执行到删除token那一步,还没将token删除掉,另一个请求也执行到删除token这一步,我们必须删除动作只能被成功执行一次) ## 文章投票 ### 需求 - 用户可以发表文章,发表时默认给自己的文章投了一票​ - 用户在查看网站时可以按评分进行排列查看​ - 用户也可以按照文章发布时间进行排序​ - 为节约内存,一篇文章发表后,7天内可以投票,7天过后就不能再投票了​ - 为防止同一用户多次投票,用户只能给一篇文章投一次票 ### redis使用sql事务 - redisTemplate.setEnableTransactionSupport(true); - 方法上加 @Transactional(rollbackFor = Exception.class) ## 计数器 - incr方法,实现id自增 ## redis 日志监控(monitor命令) 使用monitor命令,可以在控制台,实时监控redis命令操作,主要用于测试环境debugger ![](https://gitee.com/shixianqing/img/raw/master/redis/monitor.png) ## Redis慢查询分析 与mysql一样:当执行时间超过阀值,会将发生时间 耗时 命令记录 ![](https://gitee.com/shixianqing/img/raw/master/redis/%E6%85%A2%E6%9F%A5%E8%AF%A2.png) ### 慢查询阀值 有两种方式,默认为10毫秒
- 动态设置6379:> config set slowlog-log-slower-than 10000 //10毫秒 - redis.conf修改:找到slowlog-log-slower-than 10000 ,修改保存即可​ 注意:slowlog-log-slower-than =0记录所有命令 -1命令都不记录​​ 使用config set完后,若想将配置持久化保存到redis.conf,要执行config rewrite ​ ### 慢查询原理 慢查询记录也是存在队列里的,slow-max-len 存放的记录最大条数,比如​设置的slow-max-len=10,当有第11条慢查询命令插入时,队列的第一条命令​就会出列,第11条入列到慢查询队列中, 可以config set动态设置,​也可以修改redis.conf完成配置​ ### 慢查询命令​ - 获取队列里慢查询的命令:slowlog get​ - 获取慢查询列表当前的长度:slowlog len //以上只有1条慢查询,返回1;​ - 对慢查询列表清理(重置):slowlog reset //再查slowlog len 此时返回0 清空;​ - 对于线上slow-max-len配置的建议:线上可加大slow-max-len的值,记录慢查询存长命令时redis会做截断,不会占用大量内存,线上可设置1000以上​ - 对于线上slowlog-log-slower-than配置的建议:默认为10毫秒,根据redis并发量来调整,对于高并发比建议为1毫秒​ - 慢查询是先进先出的队列,访问日志记录出列丢失,需定期执行slow get,将结果存储到其它设备中(如mysql) ## redis-cli详解 - ./redis-cli -r 3 -a 12345678 ping //返回pong表示127.0.0.1:6379能通,正常​ - ./redis-cli -r 100 -i 1 info |grep used_memory_human //每秒输出内存使用量,输100次​ - ./redis-cli -p 6379 -a 12345678​ 对于我们来说,这些常用指令以上可满足,但如果要了解更多​执行redis-cli --help, 可百度 ## redis-server详解 - ./redis-server ./redis.conf & //指定配置文件启动​ - ./redis-server --test-memory 1024 //检测操作系统能否提供1G内存给redis, 常用于测试,想快速占满机器内存做极端条件的测试,可使用这个指令 ## redis-benchmark详解 redis-benchmark -c 100 -n 10000​ 测试命令事例:​ - redis-benchmark -h 192.168.42.111 -p 6379 -c 100 -n 100000 ​ 100个并发连接,100000个请求,检测host为localhost 端口为6379的redis服务器性能 ​ - redis-benchmark -h 192.168.42.111 -p 6379 -q -d 100 ​ 测试存取大小为100字节的数据包的性能​ - redis-benchmark -t set,lpush -n 100000 -q​ 只测试 set,lpush操作的性能​ - redis-benchmark -n 100000 -q script load "redis.call('set','foo','bar')"​ 只测试某些数值存取的性能​ ## pipeline ### pipeline出现的背景 redis客户端执行一条命令分4个过程:​ 发送命令-〉命令排队-〉命令执行-〉返回结果​ 这个过程称为Round trip time(简称RTT, 往返时间),mget mset有效节约了RTT,但大部分命令(如hgetall,并没有mhgetall)不支持批量操作,需要消耗N次RTT ,这个时候需要pipeline来解决这个问题​ ### Pipeline作用 1. 未使用pipeline执行N条命令 ![](https://gitee.com/shixianqing/img/raw/master/redis/%E6%9C%AA%E4%BD%BF%E7%94%A8pipeline%E6%89%A7%E8%A1%8CN%E6%9D%A1%E5%91%BD%E4%BB%A4.png) 2. 使用了pipeline执行N条命令 ![](https://gitee.com/shixianqing/img/raw/master/redis/%E4%BD%BF%E7%94%A8%E4%BA%86pipeline.png) 3. 性能对比 ![](https://gitee.com/shixianqing/img/raw/master/redis/%E6%80%A7%E8%83%BD%E5%AF%B9%E6%AF%94.png) 这是一组统计数据出来的数据​ 使用Pipeline执行速度与逐条执行要快,特别是客户端与服务端的​ 网络延迟越大,性能体能越明显 ### 原生批命令(mset, mget)与Pipeline对比 1. 原生批命令是原子性,pipeline是非原子性(原子性概念:一个事务是一个不可分割的最小工作单位,要么都成功要么都失败。​原子操作是指你的一个业务逻辑必须是不可拆分的. 处理一件事情要么都成功​ 要么都失败,其实也引用了生物里概念,分子-〉原子,原子不可拆分) 2. 原生批命令一命令多个key, 但pipeline支持多命令(存在事务),非原子性 ​ 3. 原生批命令是服务端实现,而pipeline需要服务端与客户端共同完成 ### Pipeline正确使用方式 1. 使用pipeline组装的命令个数不能太多,不然数据量过大,​ 2. 增加客户端的等待时间,还可能造成网络阻塞,​ 3. 可以将大量命令的拆分多个小的pipeline命令完成​ ## redis事务 1. pipeline是多条命令的组合,为了保证它的原子性,redis提供了简单的事务。​ redis的简单事务,将一组需要一起执行的命令放到multi和exec两个​命令之间,其中multi代表事务开始,exec代表事务结束. ​ 2. watch命令:使用watch后, multi失效,事务失效​ ​总结:redis提供了简单的事务,不支持事务回滚 ## LUA语言与Redis LUA脚本语言是C开发的,类似存储过程​ 使用脚本的好处如下:​ 1.减少网络开销;​ 2.原子操作;​ 3.复用性。​ ### LUA执行逻辑 ![](https://gitee.com/shixianqing/img/raw/master/redis/lua%E6%89%A7%E8%A1%8C%E9%80%BB%E8%BE%91.png) ### redis对Lua脚本的管理 1. 将Lua脚本加载到redis中​ 2. 检查脚本加载是否成功​ 3. 清空Lua脚本内容​ 4. 杀掉正在执行的Lua脚本 ## 发布与订阅​ redis提供了“发布、订阅”模式的消息机制,其中消息订阅者与发布者不直​接通信,发布者向指定的频道(channel)发布消息,订阅该频道的每个客​户端都可以接收到消息 ![](https://gitee.com/shixianqing/img/raw/master/redis/%E5%8F%91%E5%B8%83%E8%AE%A2%E9%98%85.png) ### 发布与订阅命令 redis主要提供发布消息、订阅频道、取消订阅以及按照模式订阅和取消订阅,​和很多专业的消息队列(kafka rabbitmq),redis的发布订阅显得很lower, 比如​无法实现消息规程和回溯, 但就是简单,如果能满足应用场景,用这个也可以 1. 发布消息:​ publish channel:test "hello world"​​ 2. 订阅消息​ subscrible channel:test​​ 3. 查看订阅数​ pubsub numsub channel:test​​ 4. 取消订阅​ unsubscribe channel:test​​ 5. 按模式订阅和取消订阅​ psubscribe ch* ​​ punsubscribe ch* ### 发布与订阅-应用场景 1. 今日头条订阅号、微信订阅公众号、新浪微博关注、邮件订阅系统​ 2. 即使通信系统​ 3. 群聊部落系统(微信群)​​​​