目录
* 1 消息投递:Exchange & RoutingKey
* 2 消费消息:Queue
* 3 路由规则:Binding
* 3.1 如何两个业务消费相同的消息?
* 3.2 一个队列也可以订阅多种消息
* 4 特殊Exchange(default)
* 5 无法路由
消息投递:Exchange & RoutingKey
在投递消息时需要指定exchange和routingKey,而不是指定队列名。
在投递消息时和kafka、rocketmq不同,消息并不是通过客户端投递到Queue中的,而是投递到Exchange,
StringBuilder线程不安全。
StringBuffer线程安全。
如果多线程同时构建一个字符串,应该使用StringBuffer,但是什么时候会多线程去构建同一个字符串呢?
在做一些生成代码或生成配置时经常会遇到命名格式不一样的问题,比如有的地方要用驼峰命名(比如代码的类和遍历),有的地方要用下划线命名(比如数据库字段)。因此写了个小工具来快速将一组单词转换成特定格式的命名。
因为我的使用场景中没有太严苛的性能要求,所以里面用到了正则,并且应该也不是最优解,所以不建议在高并发的场景用(也没做过性能测试)。
在查规范的时候学习到了一些有意思的单词,很形象的形容了命名格式。
比如下划线命名是snake,纯大写的下划线命名(比如常量定义AAA_BBB_CCC)是screaming snake(尖叫蛇)。
大驼峰是pascal(这个其实不太理解为什么是帕斯卡)。
用横线命名(比如url、域名、docker服务名:aaa-bbb-ccc)是kebab(烤肉串)。
<?php
/**
* Created
目录
* 1 数组
* 2 根据Key定位到数组
* 3 处理碰撞的问题
* 4 效率与扩容
* 5 附:完整实现
数组
HashMap底层本质上是一个固定长度的数组
根据Key定位到数组
HashMap的“hash”其实就是对key做哈希,比如将所有字符的charCode加起来然后再除以数组长度后取模(只是举个简单的例子,比一定要用这种算法,无论用那种算法,都会尽量保证当key足够多时,哈希后的结果能正态分布)。这样无论传什么key最终都会被转换成某一个数组下标,并且相同的key两次调用时获得的数组下标肯定是一样的。
class HashMap {
/** @type {*[]} */
_array = [];
/** @type {number} */
_size
缓存穿透
问题:当访问一个不存在的商品id时因为没有缓存会直接查数据库,如果有高并发访问不存在的id可能导致数据库压力变大。
解决方法:可以把空值也进行缓存,但缓存时间可以相对较低
缓存雪崩
问题:如果大量商品的缓存是在同一时间生成的,比如每天零点跑脚本更新缓存,会导致1点时大量缓存同时过期,这时会出现大量数据库查询。
解决方法:可以将过期时间加上一些随机因子,比如过期时间随机设置为为45分钟至1小时15分。
缓存击穿
问题:缓存未生成或过期后,突然高并发访问。因为生成缓存需要一定的时间,所以在这段时间并发请求都认为缓存不存在都去查数据库。
解决方法1:设置不过期的缓存(在修改数据时再更新缓存)
解决方法2:在缓存的数据中也记录一个时间,但比缓存的过期时间短。比如缓存1小时,数据中记半个小时。半小时后再访问这条数据时仍然从缓存中返回数据,但是同时会往消息队列中发一条请求更新缓存的消息。然后后台任务消费消息时去更新缓存,