1、mysql的搜索引擎有哪些,有什么区别
- MyISAM
- 特性
- 不支持事务:MyISAM存储引擎不支持事务,所以对事务有要求的业务场景不能使用
- 表级锁定:其锁定机制是表级索引,这虽然可以让锁定的实现成本很小但是也同时大大降低了其并发性能
- 读写互相阻塞:不仅会在写入的时候阻塞读取,MyISAM还会在读取的时候阻塞写入,但读本身并不会阻塞另外的读
- 只会缓存索引:MyISAM可以通过key_buffer缓存以大大提高访问性能减少磁盘IO,但是这个缓存区只会缓存索引,而不会缓存数据
- 适用场景
- 不需要事务支持(不支持)
- 并发相对较低(锁定机制问题)
- 数据修改相对较少(阻塞问题)
- 以读为主
- 数据一致性要求不是非常高
- 最佳实践
- 尽量索引(缓存机制)
- 调整读写优先级,根据实际需求确保重要操作更优先
- 启用延迟插入改善大批量写入性能
- 尽量顺序操作让insert数据都写入到尾部,减少阻塞
- 分解大的操作,降低单个操作的阻塞时间
- 降低并发数,某些高并发场景通过应用来进行排队机制
- 对于相对静态的数据,充分利用Query Cache可以极大的提高访问效率
- MyISAM的Count只有在全表扫描的时候特别高效,带有其他条件的count都需要进行实际的数据访问
- 特性
- InnoDB
- 特性
- 具有较好的事务支持:支持4个事务隔离级别,支持多版本读
- 行级锁定:通过索引实现,全表扫描仍然会是表锁,注意间隙锁的影响
- 读写阻塞与事务隔离级别相关
- 具有非常高效的缓存特性:能缓存索引,也能缓存数据
- 整个表和主键以Cluster方式存储,组成一颗平衡树
- 所有Secondary Index都会保存主键信息
- 适用场景
- 需要事务支持(具有较好的事务特性)
- 行级锁定对高并发有很好的适应能力,但需要确保查询是通过索引完成
- 数据更新较为频繁的场景
- 数据一致性要求较高
- 硬件设备内存较大,可以利用InnoDB较好的缓存能力来提高内存利用率,尽可能减少磁盘 IO
- 最佳实践
- 主键尽可能小,避免给Secondary index带来过大的空间负担
- 避免全表扫描,因为会使用表锁
- 尽可能缓存所有的索引和数据,提高响应速度
- 在大批量小插入的时候,尽量自己控制事务而不要使用autocommit自动提交
- 合理设置innodb_flush_log_at_trx_commit参数值,不要过度追求安全性
- 避免主键更新,因为这会带来大量的数据移动
- 特性
- NDBCluster
- 特性
- 分布式:分布式存储引擎,可以由多个NDBCluster存储引擎组成集群分别存放整体数据的一部分
- 支持事务:和Innodb一样,支持事务
- 可与mysqld不在一台主机:可以和mysqld分开存在于独立的主机上,然后通过网络和mysqld通信交互
- 内存需求量巨大:新版本索引以及被索引的数据必须存放在内存中,老版本所有数据和索引必须存在与内存中
- 适用场景
- 具有非常高的并发需求
- 对单个请求的响应并不是非常的critical
- 查询简单,过滤条件较为固定,每次请求数据量较少,又不希望自己进行水平Sharding
- 最佳实践
- 尽可能让查询简单,避免数据的跨节点传输
- 尽可能满足SQL节点的计算性能,大一点的集群SQL节点会明显多余Data节点
- 在各节点之间尽可能使用万兆网络环境互联,以减少数据在网络层传输过程中的延时
- 特性
- Memory
- 特性
- 速度快,采用的逻辑存储介质是系统内存
- 虽然在内存中存储表数据确实会提供很高的性能,但当mysqld守护进程崩溃时,所有的Memory数据都会丢失
- 适用场景
- 目标数据较小,而且被非常频繁地访问。在内存中存放数据,所以会造成内存的使用,可以通过参数max_heap_table_size控制Memory表的大小,设置此参数,就可以限制Memory表的最大大小。
- 如果数据是临时的,而且要求必须立即可用,那么就可以存放在内存表中。
- 存储在Memory表中的数据如果突然丢失,不会对应用服务产生实质的负面影响。
- 最佳实践
- Memory同时支持散列索引和B树索引。B树索引的优于散列索引的是,可以使用部分查询和通配查询,也可以使用<、>和>=等操作符方便数据挖掘。散列索引进行“相等比较”非常快,但是对“范围比较”的速度就慢多了,因此散列索引值适合使用在=和<>的操作符中,不适合在<或>操作符中,也同样不适合用在order by子句中。
2、hashmap等集合的线程安全问题,如何实现线程安全
a、使用Hashtable替代HashMap
当一个线程访问HashTable的同步方法时,其他线程如果也要访问同步方法,会被阻塞住。举个例子,当一个线程使用put方法时,另一个线程不但不可以使用put方法,连get方法都不可以。效率很低,所以都不会用。
Hashtable内方法上使用了synchronized。
b、类ConcurrentHashMap定义Map
源码是:
package java.util.concurrent;
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
implements ConcurrentMap<K,V>, Serializable {
...
}
ConcurrentHashMap是JUC包中的一个类,方法内部使用了synchronized保证线程安全。
c、Collections 类的synchronizedMap(Map<K,V> m)方法可以返回一个线程安全的Map
举例:
Map<String, Integer> crunchifySynchronizedMapObject = Collections.synchronizedMap(new HashMap<String, Integer>());
经测试,ConcurrentHashMap生成的Map性能是明显优于Hashtable和Collections 的synchronizedMap()方法。
3、多线程的实现方式有哪些(四种)
4、synchronize和volatile的区别
synchronize:可以是实现原子性、可见性、有序性;适用于多个共享资源;重量级,可以修饰方法
volatile:可以实现可见性、有序性;适用于一个共享资源,在没有多个共享资源参与运算的情况下可以保证原子性;轻量级,只能修饰变量
5、如何是实现三个线程t1,t2,t3
t1.start();t1.jion();t2.start();t2.join();t3.start();
6、spring是如何实现单例模式