内容:
①redis进阶使用
②redis作为数据库/缓存的区别
③缓存常见问题,面试回答思路
④redis的持久化
redis各功能的文档获取地址:http://www.redis.cn/documentation.html、
->yum install nc(netcat)
->nc localhost 6379 (与redis建立一个socket连接)
->echo -e "sdfsdf\nsdfsdf" (输出“sdfsdf”换行“sdfsdf”,echo加个-e,可以识别换行符)
->echo -e "set k2 99\nincr k2\n get k2" | nc localhost 6379 (将echo的输出不打印到屏幕,而是通过管道的方式交给nc 创建一个localhost socket连接里面去)
管道:为了让通信的成本变低
redis冷启动:从文件中批量加入数据,管道,例如:cat d1.txt | redis-cli --pipe
但值得注意的是,linux \n就换行了,windows \r\n才是换行,而d1.txt需要看到\r\n表示换行。
发布订阅功能@pubsub:
->(客户端1:6379)publish ooxx(通道) hello(消息)
->(客户端2:6379)subscribe ooxx
在监听之后,发布的消息才收到。
需求:客户需要实时性的消息,也需要看历史性的消息(3天之内或更老的)。
数据:全量一定在数据库里,一般会选择拿redis做缓存:解决数据库的读请求。
实时性:使用redis发布/订阅的功能
3天之内:使用sorted_set
更老的数据:数据库
redis事务:@transactions
->multi 发起事务
->exec 执行事务
->discard 取消事务
->watch 监控事务(执行事务之前,先看看watch的东西有没有变)
redis在事务执行失败时,不进行回滚,而是继续执行余下的命令
谁的exec先到达,先执行谁的事务
->multi (开启事务)
->set k1 aaa (并没有执行,放在队列里)
->ser k2 bbb (同上)
->exec (执行事务)
----------------------------------------------
(客户端1)->multi
(客户端2)->multi
(客户端1)->get k1
(客户端2)->del k1
(客户端2)->exec(客户端2先提交)
(客户端1)->exec(空,nil)
----------------------------------------------
(客户端1)->watch k1
(客户端1)->multi
(客户端1)->get k1
(客户端1)->keys *
(客户端2)->multi
(客户端2)->keys *
(客户端2)->set k1 asdsfaasdsad
(客户端2)->exec ( k2先执行)
(客户端1)->exec (nil,等于说事务没执行,因为k1的值被更改了)
----------------------------------------------
redis Modules(缓存穿透/布隆过滤器)
https://redis.io/modules 可以向redis增加扩展库来丰富redis的功能
RedisBloom(布隆过滤器):
https://github.com/RedisBloom/RedisBloom:Building and Loading RedisBloom
在window系统中,扩展库是.dll;在linux系统中,扩展库是.so:
$ redis-server --loadmodule /path/to/redisbloom.so
->cd soft/
->wget https://github.com/RedisBloom/RedisBloom/archive/master.zip
->yum install unzip
->unzip master.zip
->cd RedisBloom-master/
->make
->cp redisbloom.so /opt/mashibing/redis5
->cd /opt/mashibing/redis5
->ll
->service redis_6379 stop
->ps -ef | grep redis
->redis-server --loadmodule /opt/mashibing/redis5/redisbloom.so /etc/redis/6379.conf(跟上加载那个配置文件)
->多了些bf.***的命令
布隆过滤器使用,目的:用小的空间去解决大量数据匹配的问题
->bf.add (解决:缓存穿透的问题,过滤用户的搜索,不处理数据库里本来就没有的数据的搜索请求,用到了布隆过滤器)
思考一个场景:如果网站有10000种商品,每种商品的名称用4个字节存储,一共4w个byte。bitmap思路,如果每个商品能用几个二进制位去表示,整体的体积会变得很小。
布隆过滤器的原理如下图(拿一点复杂度,换时间成本。它是概率解决问题,不能100%阻挡用户的恶意请求,能让恶意请求概率降到低于1%):
1.先找到公司有的东西,再通过一个映射,把它在bitmap中标识出来。
2.如果用户搜的东西,公司有,一定能全算出曾经标识的1,就放行到关系数据库。部分没有的,可能映射函数都是1,有一定概率被放行过去;如果经过映射函数,落到0身上,那肯定是没有的。
以上三种模式一般选择第三种模式,符合微服务架构,client只负责业务代码,其他内容分出去。
作业:过滤器的知识,bloom过滤器的知识,counting bloom,布谷鸟过滤器
->bf.add ooxx abc
->bf.exists ooxx abc ("1")
->bf.exists ooxx asdasd ("0")
->cf.*(tab转换方法)
redis作为数据库/缓存的区别:
1.缓存数据不重要
2.缓存不是全量数据
3.缓存应该随着访问变化,热数据
redis作为缓存->redis里的数据怎么能随着业务变化,只保留热数据,因为内存大小是有限的,也就是瓶颈。涉及到一下几个知识点(数据清除的逻辑):
1.key的有效期<-由业务逻辑推动,比如以天为单位变化
2.内存是有限的,随着访问的变化,应该淘汰掉冷数据<-业务运转推动
->vi /etc/redis/6379.conf(看配置文件)
配置文件里有两项:
1.maxmemory <bytes>
2.maxmemory-policy noeviction(默认的策略)
参考:http://www.redis.cn/topics/lru-cache.html
noeviction:没空间了直接返回error,作为数据库时使用,要保证数据的完整性
做缓存可以选如下:
LRU:回收最近最久未使用(时间),如果缓存里大量的key做了过期的配置,优先使用volitile-lru,如果没做过期的,靠redis自己淘汰,就选allkeys-lru。
LFU:最近最少使用(次数)
random:随机
ttl:回收马上就要过期的
->set k1 aaa ex 20(有效期20s)
->get k1 (有效期不会随着查询的延长,倒计时不会延长)
->ttl k1
->set k1 aaa
->expire k1 50(设置50s过期)
->set k1 bbb(如果发生了写,会直接剔除过期时间)
->ttl k1 (变成-1了)
->expireat k1 timestemp(定时删除,“到”某个timestemp就把这个key给删了)
时间时间,由业务逻辑自己控制。
http://www.redis.cn/commands/expire.html:redis如何淘汰过期的key
过期判定原理(目的:稍微牺牲内存,但是保证redis的性能为王):
1.被动访问时判定(当一些客户端尝试访问它时,key会被发现并主动的过期)
2.周期轮询判定(增量),详见上面网站讲解