首页 > 编程语言 >慢查询、pipline、发布订阅、 bitmap位图、 hyperloglog、geo、持久化

慢查询、pipline、发布订阅、 bitmap位图、 hyperloglog、geo、持久化

时间:2024-07-01 18:42:48浏览次数:19  
标签:count --- hyperloglog -- redis bitmap pipe 位图 conn

【慢查询】

 1 # 1 我们配置一个时间,如果查询时间超过了我们设置的时间,我们就认为这是一个慢查询
 2 # 2 慢查询是一个先进先出的队列,固定长度,保存在内存中--->通过设置慢查询,以后超过我们设置时间的命令,就会放在这个队列中
 3 # 3 后期我们通过查询这个队列,过滤出 慢命令--》优化慢命令
 4 
 5 
 6 # 4 实操:
 7     1 配置慢查询
 8     # 设置记录所有命令
 9     config set slowlog-log-slower-than 0
10     # 最多记录100条
11     config set slowlog-max-len 100
12     # 持久化到本地配置文件
13     config rewrite
14     
15     2 查看慢查询队列
16     slowlog get [n]  #获取慢查询队列
17         '''
18         日志由4个属性组成:
19         1)日志的标识id
20         2)发生的时间戳
21         3)命令耗时
22         4)执行的命令和参数
23         '''
24      slowlog len #获取慢查询队列长度
25     slowlog reset #清空慢查询队列
26     
27     
28 # mysql : slow_query_log

【pipline命令管道】

  1 #1 Redis的pipeline(管道)功能在命令行中没有,但redis是支持pipeline的,而且在各个语言版的client中都有相应的实现
  2 
  3 # 2 pipeline期间将“独占”链接,多个命令,放到一个pipline(管道中),要么都执行,要么都不执行
  4 
  5 # 3 python中使用pipline
  6 import redis
  7 
  8 pool = redis.ConnectionPool(host='192.168.241.129', port=6379, password='jh123')
  9 conn = redis.Redis(connection_pool=pool)
 10 # pipe = r.pipeline(transaction=False)
 11 # 创建pipeline
 12 pipe =conn.pipeline(transaction=True)
 13 # 开启事务
 14 pipe.multi()
 15 
 16 pipe.set('name', 'jh')
 17 # 其他代码,可能出异常
 18 pipe.set('role', 'nb')
 19 
 20 pipe.execute()
 21 
 22 
 23 # 4 事务四大特性
 24     -原子性
 25     -持久性
 26     -一致性
 27     -隔离性
 28 # 6 redis有没有事务,能不能有这四大特性?
 29     -因为redis,能实现事务的四大特性---》咱们说它支持
 30     -通过pipline实现原子性--》通过pipline可以实现事务
 31     -pipline只支持单实例,集群环境,不支持---》集群环境不支持事务
 32     
 33     
 34 # 7 原生操作,实现乐观锁
 35 
 36 # 7.1 mutil  开启事务,放到管道中一次性执行
 37 multi   # 开启事务
 38 set name xxxx
 39 set age 18
 40 exec ,然后再去查,就发现数据改了
 41 
 42 
 43 # 7.2 模拟事务回顾 ,乐观锁
 44 # 在开启事务之前,先watch
 45 watch age
 46 multi
 47 decr age
 48 exec
 49 
 50 # 另一台机器
 51 multi
 52 decr age
 53 exec  # 先执行,上面的执行就会失败(乐观锁,被wathc的事务不会执行成功)
 54 
 55 
 56 
 57 # 7.3 使用redis实现乐观锁
 58 
 59 
 60 ## 利用redis的乐观锁,实现秒杀系统的数据同步(基于watch实现),
 61 ## 用户1 
 62 import redis
 63 conn = redis.Redis(host='192.168.241.129',port=6379)
 64 with conn.pipeline() as pipe:
 65     # 先监视,自己的值没有被修改过
 66     conn.watch('count')
 67     # 事务开始
 68     pipe.multi()
 69     old_count = conn.get('count')
 70     count = int(old_count)
 71     input('我考虑一下')
 72     if count > 0:  # 有库存
 73         pipe.set('count', count - 1)
 74 
 75     # 执行,把所有命令一次性推送过去
 76     ret = pipe.execute()
 77     print(type(ret))
 78     print(ret)
 79 ## 用户2
 80 import redis
 81 conn = redis.Redis(host='127.0.0.1',port=6379)
 82 with conn.pipeline() as pipe:
 83     # 先监视,自己的值没有被修改过
 84     conn.watch('count')
 85     # 事务开始
 86     pipe.multi()
 87     old_count = conn.get('count')
 88     count = int(old_count)
 89     if count > 0:  # 有库存
 90         pipe.set('count', count - 1)
 91     # 执行,把所有命令一次性推送过去
 92     ret=pipe.execute()
 93     print(type(ret))
 94 
 95 # 注:windows下如果数据被修改了,不会抛异常,只是返回结果的列表为空,mac和linux会直接抛异常
 96 
 97 # 秒杀系统核心逻辑测试,创建100个线程并发秒杀(代码有问题)
 98 import redis
 99 from threading import Thread
100 def choose(name, conn):
101     with conn.pipeline() as pipe:
102         # 先监视,自己的值没有被修改过
103         conn.watch('count')
104         # 事务开始
105         pipe.multi()
106         old_count = conn.get('count')
107         count = int(old_count)
108         # input('我考虑一下')
109         # time.sleep(random.randint(1, 2))
110         if count > 0:  # 有库存
111             pipe.set('count', count - 1)
112 
113         # 执行,把所有命令一次性推送过去
114         ret = pipe.execute()
115         print(ret)
116         if len(ret) > 0:
117             print('第%s个人抢购成功' % name)
118         else:
119             print('第%s个人抢购失败' % name)
120 
121 
122 if __name__ == '__main__':
123     conn = redis.Redis(host='192.168.241.129', port=6379)
124     for i in range(100):
125 
126         t = Thread(target=choose, args=(i, conn))
127         t.start()

【发布订 1 # 发布订阅(观察者模式):发布者发布了消息,所有的订阅者都可以收到,就是生产者消费者模型

 2     -生产者消费者 发布订阅模型
 3     -生产者消费者 队列
 4     
 5 # 原生实现
 6     -发布消息:
 7         publish channel message 
 8     -订阅(现有订阅者,然后发布者才有消息)
 9         subscribe channel
10     -接收消息
11         -只要发布者一发布,订阅者都会受到
12         
13         
14 # python+redis实现
15 import redis
16 # 连接到Redis服务器
17 r = redis.Redis(host='localhost', port=6379, db=0)
18 # 发布者
19 20 r.publish('channel', 'message')
21  
22     
23     
24 import redis
25 # 连接到Redis服务器
26 r = redis.Redis(host='localhost', port=6379, db=0)  
27 # 订阅者
28 sub = r.pubsub()
29 sub.subscribe('channel')
30 for message in sub.listen():
31     print(message)
    

if isinstance(message['data'],bytes):
print(message['data'].decode('utf-8'))
if message['data'].decode('utf-8')['type']=='下单':
print(message['data'].decode('utf-8')['user'],'发送短信')

 。

【bitmap位图】

 1 #1 本质是字符串
 2 
 3 #2 操作比特位
 4   b         i        g
 5 01100011  01101001   01100111
 6 set hello big #放入key位hello 值为big的字符串
 7 getbit hello 0 #取位图的第0个位置,返回0
 8 getbit hello 1 #取位图的第1个位置,返回1 如上图
 9 
10 # 我们可以直接操纵位
11 setbit key offset value #给位图指定索引设置值
12 setbit hello 7 1 #把hello的第7个位置设为1 这样,big就变成了cig
13 
14 
15 # 3 独立用户统计---》统计日活---》用户量足够大--》节约内存
16     -10亿用户  用户id1 2  3  10亿
17     
18     1个bytes--》8个比特位---》能表示多少种变化?
19         2的7次方-1 :-128 到127之间
20     8个bytes--》64个比特位--》9223372036854775808
21     
22     如果以集合存储:存一个用户,就要8个bytes---》存1亿用户 8 bytes*1亿
23     
24     -统计日活,只要用户登录,就把用户id放到集合中
25     -晚上只需要统计一下 集合大小---》就能统计出日活   
26     -使用集合存储---》1--》32位--》1亿用户 5千万左右---》需要 200MB空间
27         int8个比特位表示范围 -128--127之间
28         int16 
29         int32 个比特位表示范围 -2的31次方---2的31次方  2147483648
30         
31     -使用位图---》12.5MB空间
32 
33     
34 # 获取前3位中1的个数
35 bitcount name 0 3 

 。

【hyperloglog】

 1 # 1 基于HyperLogLog算法:极小的空间完成独立数量统计,本质还是字符串
 2 
 3 # 2 
 4     -放值:pfadd uuids "uuid1" "uuid2" "uuid3" "uuid4"
 5     -统计个数:pfcount uuids
 6     -判断一个值是否在里面:pfadd uuids "uuid1"(返回1/0)
 7       
 8 # 3 统计日活用户
 9 
10 # 4 去重:爬过的网址,就不爬了--》存一下爬过的
11 'www.baidu.com'--->放到 pfadd 中--》返回1,说明没爬过--》继续爬取--》如果返回0,不爬了
12 
13 # 5 黑白名单
14 
15 # 6 注意
16 百万级别独立用户统计,百万条数据只占15k
17 错误率 0.81%
18 无法取出单条数据,只能统计个数
19 
20 # 7 类似于布隆过滤器,算法不一样

【geo】

 1 # 1 geo 地理位置信息
 2 GEO(地理信息定位):存储经纬度,计算两地距离,范围等
 3 北京:116.28,39.55
 4 天津:117.12,39.08
 5 可以计算天津到北京的距离,天津周围50km的城市,外卖等
 6 
 7 # 2 经纬度哪里来?
 8     - web端:js获取--》掉接口,传给后端
 9     - 安卓,ios端:线程的代码
10     -微信小程序
11           
12 # 3 js获取经纬度
13 if (navigator.geolocation) {
14   navigator.geolocation.getCurrentPosition(function(position) {
15     var latitude = position.coords.latitude;
16     var longitude = position.coords.longitude;
17     console.log("经度:" + longitude);
18     console.log("纬度:" + latitude);
19   });
20 } else {
21   console.log("浏览器不支持Geolocation API");
22 }
23 
24 
25 # 4 增加地理位置信息
26 geoadd key longitude latitude member #增加地理位置信息
27 
28 geoadd cities:locations 116.28 39.55 beijing #把北京地理信息天津到cities:locations中
29 geoadd cities:locations 117.12 39.08 tianjin
30 geoadd cities:locations 114.29 38.02 shijiazhuang
31 geoadd cities:locations 118.01 39.38 tangshan
32 geoadd cities:locations 115.29 38.51 baoding
33 
34 
35 # 5 获取天津的经纬度  geopos key member #获取地理位置信息
36 geopos cities:locations tianjin
37 # 根据经纬度--》文字
38 from geopy.geocoders import Nominatim
39 geolocator = Nominatim(user_agent="my_application")
40 def geolocate_point(latitude, longitude):
41     location = geolocator.reverse(f"{latitude}, {longitude}")
42     return location.address
43 # 示例使用经纬度
44 latitude = 39.983424
45 longitude = 116.307224
46 address = geolocate_point(latitude, longitude)
47 print(address)
48 
49 # 6 统计两个地理位置之间的距离
50 geodist cities:locations beijing tianjin km #北京到天津的距离,89公里
51 
52 # 7 统计某个地理位置方圆xx公里,有xx
53 georadiusbymember cities:locations beijing 150 km

【持久化】

 1 # 1 什么是持久化
 2 redis的所有数据保存在内存中,对数据的更新将异步的保存到硬盘上
 3 
 4 # 2 持久化的实现方式
 5 快照:某时某刻数据的一个完成备份,
 6      -mysql的Dump:写一个mysql自动定时备份和清理前后端程序
 7     -redis的RDB:某一刻,把内存中得数据,保存到硬盘上这个操作就是rbd的持久化
 8 写日志:任何操作记录日志,要恢复数据,只要把日志重新走一遍即可
 9     -mysql的 Binlog
10     -Redis的 AOF
11     
12 # 3 redis有三种持久化方案
13     -rdb:快照
14     -aof:日志
15     -混合持久化:rdb+aof混合方案

rdb

 1 # 4 rdb方案 :三种方式
 2     1 人工同步:客户端 : save  # 同步操作,会阻塞其他命令--》单线程架构
 3     2 人工异步:客户端:bgsave  # 异步操作,不会阻塞其他命令
 4     3 配置文件
 5         save 900 1 #配置一条
 6         save 300 10 #配置一条
 7         save 60 10000 #配置一条
 8 
 9         save 60 5
10 
11 # 5 最佳配置
12 #最佳配置
13 save 900 1 
14 save 300 10 
15 save 60 10000 
16 dbfilename dump-6379.rdb  #以端口号作为文件名,可能一台机器上很多reids,不会乱
17 dir ./bigdiskpath #保存路径放到一个大硬盘位置目录
18 stop-writes-on-bgsave-error yes #出现错误停止
19 rdbcompression yes #压缩
20 rdbchecksum yes #校验
21 
22 
23 # 6 确定 RDB问题
24     耗时,耗性能:
25     不可控,可能会丢失数据

aof

1 # 1 客户端每写入一条命令,都记录一条日志,放到日志文件中,如果出现宕机,可以将数据完全恢复
2 # 2 AOF的三种策略日志不是直接写到硬盘上,而是先放在缓冲区,缓冲区根据一些策略,写到硬盘上always:redis–》写命令刷新的缓冲区—》每条命令fsync到硬盘—》AOF文件everysec(默认值):redis——》
写命令刷新的缓冲区—》每秒把缓冲区fsync到硬盘–》AOF文件no:redis——》写命令刷新的缓冲区—》操作系统决定,缓冲区fsync到硬盘–》AOF文件​ 3 # 3 配置文件appendonly yes #将该选项设置为yes,打开appendfilename "appendonly-${port}.aof" 4 #文件保存的名字appendfsync everysec 5 #采用第二种策略dir /bigdiskpath 6 #存放的路径no-appendfsync-on-rewrite yes​​appendonly yesappendfilename "appendonly.aof"appendfsync everysecno-appendfsync-on-rewrite yes​​ 7 8 # 4 放在了文件中appendonly.aof.1.base.rdb :永久的appendonly.aof.1.incr.aof :临时的appendonly.aof.manifest: 哪些文件存了数据

 

标签:count,---,hyperloglog,--,redis,bitmap,pipe,位图,conn
From: https://www.cnblogs.com/liuliu1/p/18278625

相关文章