# redis > something redis is not a good choice, something redis is just ok, but redis is so easy 关于持久化和数据查询的相关技术 -> 关系型数据库再也不是放之四海皆准 -> 围绕数据的解决方案不可能再只有唯一一种 redis: 容易学习; 在处理一组特定的问题集的同时能保持相当的通用性 -> 什么是可行的,什么是不应该由Redis来处理的 - [try redis](http://try.redis.io/) - [the little redis book](https://github.com/JasonLai256/the-little-redis-book/blob/master/cn/redis.md) - [redis.cn](http://www.redis.cn/documentation.html): 文档/月报 - [Redis的数据类型——探究竟](https://mp.weixin.qq.com/s/Jve5RPYsSBsMtK1Lqo66Sg) - [aliyun redis 开发规范](https://yq.aliyun.com/articles/531067) - [redis的陈年往事](https://mp.weixin.qq.com/s/8-GxH4_WjoRe8DwFlk3qNw) - [redis过期及逐出策略](https://help.aliyun.com/knowledge_detail/55892.html) - [redis重要知识点](https://github.com/Weiwf/redis-mindmap) ## 最佳实践 - key命名: `业务:子业务:id` -> 可读/简洁/不含转义字符 - 过期时间 - 高危操作: flushdb flushall keys monitor - 加锁: 1 == redis->incr(key) - 游戏玩家积分排行版: zset - 网上商城商品相关性分析: 为每种商品构建一个有序集合 -> score 为商品同时出现的次数 - pub/sub: 消息「非持久」 pub非独占 sub独占阻塞 - 数据集成(Data Integration): mysql -> redis - 热点: client -> slb -> proxy(读写分离, 本地缓存->热点数据+技术) -> master(write) - slave(backup) - read - 用户关注列表: hash uid-uid-value - 评论游标分页: zset(id-timestamp) + hash(comment-id-content) - redis 内存分析: pip install rdbtools + sqlite - 秒杀: 秒杀前-商品详情页-浏览器缓存/CDN -> 秒杀开始-redis读写分离/数据(flag/all/donebooked) -> 库存-hash(all/booked)/lua脚本原子性 -> 落库-list - 大量key操作: scan 分批 找到索引边界 批量(hmset pipeline) - redis所有请求对不存在的key都有输出返回, 比如 ttl -2 -> 减少不必要的请求 - 避免value过大: 1k-性能拐点 MTU-1.5k ## base 入门 ``` # key-value set key value # 常使用 : 作为key的分隔符 get key setnx key # set if not exist incr key # incr 并发安全 del key expire / expireat / ttl / persist # 过期, ttl->time to live strlen getrange append # string类型的value # list lpush/rpush list value.. lpop/rpop list llen list lrange list 0 -1 # 查看所有 ltrim list 0 -1 # 只留下范围内的值, 其他删除 lindex/lset # 通过索引获取值/通过索引设置值 # set sadd set value srem set value # remove sismember set value smembers set sunion s1 s2 sinter s1 s2 # 是否有共同元素 sinterstore s1 s2 s3 # 存储共同元素 # sorted set zadd set score value # score is float number zrange set 0 -1 zcount z s1 s2 # 按照 score 进行 count zrank / zrevzank # 升序/降序 # hash hset h field value hmset h f1 v1 f2 v2 ... hget h f hgetall h hincrby h f num # increment to a num value hdel h f # HyperLogLog pfadd key v1 v2 pfcount key pfmerge new key1 key2 # pub/sub subscribe / unsubscribe # 订阅 psubscribe # 模式匹配订阅 publish channel value blpop / brpop / blpush / brpush # pipeline: 批量操作 # eval + lua eval code script load / evalsha # 加载脚本后返回 sha1 值, 通过 sha1 值执行脚本 # transaction multi ...do something exec / discard # 非严格意义上事务->操作失败/discard->不回滚 watch / unwatch # CAS 乐观锁 # more redis-cli --raw # 中文乱码 redis-benchmark # 类似 ab 1w~10w/s redis-server # 启动时没有指定 conf, redis将采用默认配置 config set slowlog-log-slower-than 0 # 修改配置 auth # 密码验证 info # 查看服务器状态 select 1 # 切换db, 默认为0, 默认有 16 个 type key # 查看 key 的数据类型 scan 0 match * count 10 # 使用 scan 替代 keys/smembers等会一次性扫描所有记录的命令; scan 返回2个值, 第一个值为游标 flushdb / flushall # 高危命令 setbit / getbit # 今天我们有多少个独立用户访问 -> 2个命令/1.28亿/50ms/16m monitor # 监控 slowlog # 慢日志 slowlog get slowlog get 10 sort # list/set/hash -> 基于bug严重级别的排序 / 大数据量双维度排序 # redis-cli 数据备份 bgsave # RDB redis-cli -h old_instance_ip -p old_instance_port config set appendonly yes redis-cli -h aliyun_redis_instance_ip -p 6379 -a password --pipe < appendonly.aof ``` - key & value: key的数据为标量, value可为任意数据类型(序列化) - Big O Notation: 许多Redis命令都具有O(1)的时间复杂度; `O(1) -> O(log(N)) -> O(N)`; N 不一定是记录总数; 发现一些操作具有O(N)的时间复杂度时 -> 可能可以找到更为好的方法去处理 - Memory and Persistence(3种方式): snapshot append-only slaveDB - Replication(复制): 配置 `slaveof` -> master-slave; 没有提供自动故障恢复 - backup(备份): Redis会把快照存储为一个名为`dump.rdb`的文件 - Scaling and Redis Cluster(缩放/集群)