Redis能做的事远不止这些,还需要在日常使用app中多加思考!
redis是业界主流的key-value nosql 数据库之一。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
redis的性能不必废话,redis4,0新加入多线程新能更高
异常快速 : Redis是非常快的,每秒可以执行大约110000设置操作,81000个/每秒的读取操作。
redis-cli链接redis客户端
redis的数据结构:string hashmap list set sorted set(zset)(有序集合)
- string:
set key value
mset key value key value
get key
mget key key - 计数器
INCR key
get key
redis是原子锁,一次只执行一条命令,原来只是单线程,现在有多线程了,用数据库文章+1,考虑并发问题需要加锁,底层也是用nio(异步io)
- redis实现session共享,session不用外部存储只会存在tomcat里面,,tomcat2里面没有,nginx负载均衡给打到tomcat2没有session,浏览器的cookie存储sessionid,没发现,那还要再次登录吗,体验非常不好。把session存在redis里面,tomcat从session里面取,这样体验就非常好了(那么需要加个逻辑,请求打过来,先做个判断,看看sessionid,获取下sessionid,如果没有直接alert提示登录,有的话根据sessionid去连redis查找一下有没有这个session,取到返回值了直接带着状态跳转主页)
- 用redis来维护数据库的id(分布式系统全局序列号),正常DBA推荐你主键自增,但是对于大型互联网做分库分表,如果还用自增来维护很可能重复。用redis的incr就可以做,自增id。但是这么做性能不高,每秒生成几万的id(并发是有瓶颈的),那怎么做?每次拿1000,在内存中慢慢的拿,大大提升了并发能力,一次性批发一批,用incrby orderid 1000直接生成1000个。
- hash场景:hset key key value(双重map),1:name,注意这个1可以是传进去的,拿到用户的id进行拼接,非常的灵活。还有很多的使用场景,手机的购物车
key:userid
key:fieldid value:fieldnum
加号:hincrby(具体怎么做,获取点击事件传一个参数,然后触发一段业务逻辑,就增加了1,如果手动输入怎么做?获取输入的数字,在redis语句中进行拼接操作)
标记数量:hlen
删除购物车:hdel cart:1001 10088
全选:hgetall
例如:hset cart:1001 10088 1(往1001用户购物车里放10088的这个商品id 数量为1)
- string:浏览量(key value)用incr
- 分布式锁:库存先查询库存,然后操作,最后重新写入库存,用redis的分布式锁
高并发的情况下,超卖怎么解决?
setnx key value 加锁的写入 返回1 表示获得锁成功
如果发现key存在setnx不会执行任何操作
执行不成功的直接返回“后端繁忙请稍后再试”,然后删除key,后面的能继续操作
- hashmap:电商购物车(key key value)
- list:微博消息和微信公众号消息
- set:微信小程序抽奖,微信微博的点赞收藏,微博微信关注模型
lpush lpull 队列的操作 从左边加入 从左边取
1.点击参与抽奖集合
2.查看所有抽奖用户
redis也有持久化,不用mysql没问题
hash的性能比string高,更加节约空间,但是有缺点,在redis集群中
有个槽位的概念,先计算槽位计算出来放在哪里访问
-
list的常用操作:
lpush key value 时间
lpop key弹出来
用list就可以形成常用的数据结构:栈 队列(先进先出)
栈:一边进一边拿
队列:一边进另一边拿
消息队列:生产者消费者(阻塞队列,有消息就拿lpush发消息,brpop拿) -
微博消息公众号消息(信息流用redis来实现)
发微博的存在消息列表里
lrange key start stop(类似于切片的操作) -
set的操作
SADD key member(点击加入抽奖集合)
smembers key 查看抽奖的集合
srem key member 删除抽奖的member
srandmember key 数量 抽取指定的人数
spop key 数量 抽中了的踢出去(分级的抽奖,几等奖几等奖) -
微信微博点赞收藏标签
scard key获取集合元素个数
sismember key member
点赞:SADD 消息 用户id
取消点赞:SREM 消息 用户id
检查用户是否点赞:sismember 消息 id
获取点赞的用户列表:smembers 消息
获取点赞的用户数:scard 消息 -
集合的运算操作
求交集(共同关注,可能认识的人)数据库设计出来这种模型太复杂了,性能也有问题
sinter set1 set2 set3
求并集
sunion set1 set2 set3
以一个为基准进行比较(可能认识的人)
sdiff set1 set2 set3
zset集合操作
- 微博热搜,等等排行榜
redis其他场景
- 微信,陌陌附近的人
- 微信摇一摇
- 打车软件,附近的车
- 饿了么,美团附近的餐馆
- 搜素自动补全
一把锁!!!
mysql:行级锁,表级锁
zookeeper的分布式锁
redis的分布式锁
读写锁,互斥锁
python实现分布式锁 https://github.com/SPSCommerce/redlock-py
go实现分布式锁 https://github.com/hjr265/redsync.go
java实现分布式锁 https://github.com/mrniko/redisson
https://blog.csdn.net/weixin_33742618/article/details/90685307
pycharm IDEA 如何开启同时运行两个程序RUN 设置Allow running in parallel选项打勾
https://blog.csdn.net/qq_32447301/article/details/79387649 容器删除 镜像删除
https://blog.csdn.net/baidu_30809315/article/details/83543803 修改flask项目启动端口
模拟实现高并发场景,压测工具jmeter,基于java,需要安装JDK 环境,本机起两个flask服务监听5000和5001端口,分别连redis,虚拟机centos7起nginx服务器,反向代理负载均衡宿主机,对外暴露统入口 192.168.137.131,浏览器访问
业务代码:
from flask import Flask
import redis
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route("/obj")
def obj():
host = '127.0.0.1'
port = 6379
pool = redis.ConnectionPool(host=host, port=port)
r = redis.Redis(connection_pool=pool)
res = int(r.get("obj"))
if res >= 0:
res -= 1
return "库存剩余 %s" % res
else:
return "库存不足"
if __name__ == '__main__':
app.run()
说明:建立一个redis连接池,每次访问之后不断开,避免了开销,业务逻辑,每次请求进来(接口:本机ip:5000(5001)/obj)都会减库存,redis设置obj 50,50个库存,压测200次请求,模拟200/s向本机的并发,测试会不会出现超卖的情况。
本机开两个server,终端只要输出有相同的库存剩余即代表出问题,需要redis分布式锁来解决。
每次修改完.conf文件就需要重启nginx
检查修改的nginx.conf配置是否正确
nginx -t
如果出现下面ok和successfull就代表正确了,其他的都不对