博客
docker 编排文件中限制内存配置如下 services: api: build: ./phpfpm hostname: bzj-api networks: hfnet: aliases: - bzj.api deploy: resources: limits: memory: 300M reservations: memory: 200M docker-compose 启动警告 WARNING: Some services (mysql, rsnmp) use the 'deploy' key, which will be ignored. Compose does not support 'deploy' configuration - use `docker stack deploy` to deploy to a swarm. 问题原因: 由于做了资源限制, 并且没有使用swarm, 所以要加上--compatibility参数, 不然会报错 解决方案在启动的时候,添加参数: docker-compose --compatibility up -d
6月前 喜欢(0) 浏览(299) 评论(0)
Wiki
很多分布式锁的做法是,这个做法如果在 setnx 之后执行 expire之前进程意外 crash 或者要重启维护了,这个锁就永远得不到释放了 public function acquire() { $result = $this->redis->setnx($this->name, $this->owner); if ($result === 1 && $this->seconds > 0) { $this->redis->expire($this->name, $this->seconds); } return $result === 1; } 可以通过以下命令实现分布式锁,因为是一条命令所以可以保证原子性 // 原生命令 set name 111 PX 10000 NX return $this->redis->set('name','111',['NX', 'PX' => 10000]);
6月前 喜欢(0) 浏览(534) 评论(0)
博客
通过配置路由,可以设置vue项目启动后默认显示的页面。路由的path设置为path:"/",启动项目后就会显示默认的组件页面。 import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) import Home from '../components/Home.vue' import View from '../components/View.vue' import ViewTwo from '../components/ViewTwo.vue' export default new Router({ routes: [ { path:"/", // path 设置为 “/” ,默认显示该页面 component:Home, name:"Home" }, { path:"/view", component:View, name:"View" }, { path:"/viewtwo", component:ViewTwo, name:"ViewTwo" } ], mode:"history", // mode 设置为history ,去掉地址栏上的 # 号 })
6月前 喜欢(0) 浏览(363) 评论(0)
博客
Method invoked that should be only be invoked inside a doPrivileged block (DP_DO_INSIDE_DO_PRIVILEGED) 代码调用了一个需要安全权限检查的方法。如果代码需要被授权为安全权限,但是可能被不安全的代码去调用,那么classloader就需要放在doPrivileged块内。 This code invokes a method that requires a security permission check. If this code will be granted security permissions, but might be invoked by code that does not have security permissions, then the invocation needs to occur inside a doPrivileged block. 代码中field.setaccessible(true) 报了findbugs 解决方法是替换成 ReflectUtils.makeAccessible(field)
7月前 喜欢(0) 浏览(528) 评论(0)
讨论
此篇,主要是演示docker-php-source , docker-php-ext-install ,docker-php-enable-docker-configure 这四个命令到底是用来干嘛的,它们在PHP容器中都做了哪些事情。 很多人很不理解在Dockerfile中安装PHP扩展的时候总是出现这几个命令,本篇就就是为你揭开这些命令的神秘面纱而准备的,所有案例都是本人自己运行过的。 Docker 中的PHP容器安装扩展的方式有 通过pecl方式安装 通过php 容器中自带的几个特殊命令来安装,这些特殊命令可以在Dockerfile中的RUN命令中进行使用。 这里,我们主要讨论的是第二种方案,如何通过PHP容器中的几个特殊命令来安装PHP扩展 PHP中安装扩展有几个特殊的命令 docker-php-source docker-php-ext-install docker-php-ext-enable docker-php-ext-configure 演示这三个命令的作用 都是在PHP容器中进行演示的,PHP容器启动太简单,不作过多介绍 https://www.cnblogs.com/yinguohai/p/11329273.html
9月前 喜欢(0) 浏览(350) 评论(0)
讨论
完整迁移,就是指,不仅将所有代码移植到新的仓库,而且要保留所有的commit记录 1.随便找个文件夹,从原地址克隆一份裸版本库 git clone --bare 旧的git地址 会在当前目录下产生一个 xxx.git 的文件夹 这个步骤,就是克隆git每一次的提交信息,和本地的代码没有关系,只要线上的代码是最新的,这个git版本就是完整的 2.推送裸版本库到新的地址 cd xxx.git git push --mirror 新的git地址 3.删掉xxx.git文件夹 删不删无所谓,只是说明它没有用了而已。 4.代码迁移就成功了,接下来就可以使用新的地址了 git clone 新的git地址
9月前 喜欢(0) 浏览(349) 评论(0)
博客
为什么要使用配置中心? 随着业务的发展,微服务架构的升级,服务的数量、应用的配置日益增多(各种微服务、各种服务器地址、各种参数),传统的配置文件方式和数据库的方式已经可能无法满足开发人员对配置管理的要求,同时对于配置的管理可能还会牵涉到 ACL 权限管理、配置版本管理和回滚、格式验证、配置灰度发布、集群配置隔离等问题,以及: 安全性:配置跟随源代码保存在版本管理系统中,容易造成配置泄漏 时效性:修改配置,需要每台服务器每个应用修改并重启服务 局限性:无法支持动态调整,例如日志开关、功能开关等 因此,我们可以通过一个配置中心以一种科学的管理方式来统一管理相关的配置。 安装 Aliyun ACM composer require hyperf/config-aliyun-acm 安装完成后,打开 config/autoload/aliyun_acm.php 配置文件 <?php return [ // 是否开启配置中心的接入流程,为 true 时会自动启动一个 ConfigFetcherProcess 进程用于更新配置 'enable' => true, // 配置更新间隔(秒) 'interval' => 5, // 阿里云 ACM 断点地址,取决于您的可用区 'endpoint' => env('ALIYUN_ACM_ENDPOINT', 'acm.aliyun.com'), // 当前应用需要接入的 Namespace 'namespace' => env('ALIYUN_ACM_NAMESPACE', ''), // 您的配置对应的 Data ID 'data_id' => env('ALIYUN_ACM_DATA_ID', ''), // 您的配置对应的 Group 'group' => env('ALIYUN_ACM_GROUP', 'DEFAULT_GROUP'), // 您的阿里云账号的 Access Key 'access_key' => env('ALIYUN_ACM_AK', ''), // 您的阿里云账号的 Secret Key 'secret_key' => env('ALIYUN_ACM_SK', ''), ]; 开通 ACM 服务 前提条件 您已注册阿里云账号并完成实名认证。 操作步骤 打开ACM 产品主页(https://www.aliyun.com/product/acm)。 在页面右上角单击登录。 在登录页面上输入您的阿里云账号和密码,并单击登录。登录成功后,您将跳转至 ACM 产品主页。 在产品主页上单击立即开通,然后在云产品开通页页面上勾选我已阅读并同意《应用配置管理服务协议》,并单击立即开通。 阿里云配置 在hyperf中添入阿里云ACM的配置 把对应信息配置到 aliyun_acm.php 中就 OK 了。 验证打印出 config('app_name')。 注意:你在 Aliyun ACM 中配置对应的参数,就会把本地的配置覆盖掉。
10月前 喜欢(0) 浏览(501) 评论(0)
置顶 博客
简介 Hyperf 是基于 Swoole 4.4+ 实现的高性能、高灵活性的 PHP 协程框架,内置协程服务器及大量常用的组件,性能较传统基于 PHP-FPM 的框架有质 的提升,提供超高性能的同时,也保持着极其灵活的可扩展性,标准组件均基于 PSR 标准 实现,基于强大的依赖注入设计,保证了绝大部分组件或类都是 可替换 与 可复用 的。 框架组件库除了常见的协程版的 MySQL 客户端、Redis 客户端,还为您准备了协程版的 Eloquent ORM、WebSocket 服务端及客户端、JSON RPC 服务端及客户端、GRPC 服务端及客户端、Zipkin/Jaeger (OpenTracing) 客户端、Guzzle HTTP 客户端、Elasticsearch 客户端、Consul 客户端、ETCD 客户端、AMQP 组件、Apollo 配置中心、阿里云 ACM 应用配置管理、ETCD 配置中心、基于令牌桶算法的限流器、通用连接池、熔断器、Swagger 文档生成、Swoole Tracker、视图引擎、Snowflake 全局 ID 生成器 等组件,省去了自己实现对应协程版本的麻烦。 Hyperf 还提供了 基于 PSR-11 的依赖注入容器、注解、AOP 面向切面编程、基于 PSR-15 的中间件、自定义进程、基于 PSR-14 的事件管理器、Redis/RabbitMQ 消息队列、自动模型缓存、基于 PSR-16 的缓存、Crontab 秒级定时任务、国际化、Validation 表单验证器 等非常便捷的功能,满足丰富的技术场景和业务场景,开箱即用。 框架初衷 尽管现在基于 PHP 语言开发的框架处于一个百家争鸣的时代,但仍旧未能看到一个优雅的设计与超高性能的共存的完美框架,亦没有看到一个真正为 PHP 微服务铺路的框架,此为 Hyperf 及其团队成员的初衷,我们将持续投入并为此付出努力,也欢迎你加入我们参与开源建设。 设计理念 Hyperspeed + Flexibility = Hyperf,从名字上我们就将 超高速 和 灵活性 作为 Hyperf 的基因。 对于超高速,我们基于 Swoole 协程并在框架设计上进行大量的优化以确保超高性能的输出。 对于灵活性,我们基于 Hyperf 强大的依赖注入组件,组件均基于 PSR 标准 的契约和由 Hyperf 定义的契约实现,达到框架内的绝大部分的组件或类都是可替换的。 基于以上的特点,Hyperf 将存在丰富的可能性,如实现 Web 服务,网关服务,分布式中间件,微服务架构,游戏服务器,物联网(IOT)等。 生产可用 我们为组件进行了大量的单元测试以保证逻辑的正确,同时维护了高质量的文档,在 Hyperf 正式对外开放之前,便已经过了严酷的生产环境的考验,我们才正式的对外开放该项目,至今,已有很多的大型/中小型互联网公司在生产环境使用 Hyperf。
10月前 喜欢(0) 浏览(1094) 评论(0)
讨论
Jenkins安装 环境要求:>=Linux kernel 3.10 、Docker; 这里主要阐述基于docker的安装,因为Jenkins官方docker镜像中已经集成好了java tomcat等环境,大量减少了我们的工作量。 步骤 准备工作 #安装docker【参考官方】 #创建Jenkins挂载目录,结构如下 > compose > docker-compose.yml > jenkins > jenkins_home > run > .ssh # 生成私钥和公钥 [root@ub-node-data ~] ssh-keygen -t rsa -C "jenkins@trmall" #拷贝到./jenkins/.ssh目录 [root@ub-node-data ~] cp -r ~/.ssh/ .ssh/ 编写docker-compose.yml 如下: jenkins: image: jenkinsci/blueocean:latest hostname: trmall-data-jenkins networks: trnet: aliases: - trmall.manager.jenkins volumes: - ../jenkins/jenkins_home:/var/jenkins_home # Jenkins主目录 - ../jenkins/run/docker.sock:/var/run/docker.sock # docker 守护进程信息 - ../jenkins/.ssh/id_rsa:/var/jenkins_home/.ssh/id_rsa # 私钥 ports: - 8080:8080 - 50000:50000 创建构建容器 docker-compose -p trmall -f /trmall/compose/docker-compose.yml up -d 容器构建成功后,访问http://ip:8080 开始安装 # 查看初始令牌 docker exec -it trmall_jenkins_1 cat /var/jenkins_home/secrets/initialAdminPassword .... 安装完成 Jenkins自动化部署任务 新建任务准备工作 添加gitLab凭据 填写Private Key 新建任务>一个自由风格的软件项目 源码管理>填写Repositories shell参考 #!/bin/bash yes 2>/dev/null|scp -r ${WORKSPACE}/* root@10.200.148.119:/trmall/projects/service-settlement # 拷贝工作空间代码到远程服务器 并输出执行过程的字符串 ssh -tt root@10.200.148.119 "/trmall/bin/update service-settlement" 至此还不可以部署噢,接下来我们还要设置免密登录,才可以实现远程执行shell 设置免密登录部署节点 还记得之前生成的私钥和公钥吗?现在就要出场了 #检查用户组,若无gid 1000的组则创建Jenkins用户组和用户【注意:这里的uid、gid 1000必须和之后容器内的Jenkins这个用户gid一致】 [root@ub-node-data ~] groupadd -g 1000 jenkins && useradd -g jenkins -u 1000 jenkins #然后将宿主机上映射目录的私钥.ssh/id_rsa所属组用户都改为Jenkins [root@ub-node-data ~] chown -R jenkins:jenkins /trmall/jenkins/.ssh/id_rsa #或直接指定组id皆可,因为容器的本地数据卷中文件/目录的权限是和宿主机上一致的,只是uid/gid在Docker容器和宿主机中可能映射为不同的用户/组名称。 [root@ub-node-data ~] chown -R 1000 /trmall/jenkins/.ssh/id_rsa #然后将公钥 id_rsa.pub 拷贝到部署节点root/.ssh下并重命名为 authorized_keys实现远程免密登陆 至此,最简单的部署实践完成;若分布式大型项目还可以应用saltstack辅助我们支持更丰富的部署解决方案。
10月前 喜欢(0) 浏览(422) 评论(0)
讨论
Redis Redis 是完全开源免费的,遵守 BSD 协议,是一个高性能的 key-value 数据库。 特点: - Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。 - Redis 不仅仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。 - Redis 支持数据的备份,即 master-slave 模式的数据备份。 原子 – Redis 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。 多个操作也支持事务,即原子性,通过 MULTI 和 EXEC指令包起来。 Redis乐观锁的实现:通过 WATCH 和 MULTI EXEC指令实现如下 127.0.0.1:6379> watch hello # watch 监控 hello 的值,在exec执行时做对比,如果值发生改变则exec提交失败(实现乐观锁) OK 127.0.0.1:6379> get hello "4" 127.0.0.1:6379> multi OK 127.0.0.1:6379> incr hello QUEUED 127.0.0.1:6379> incr hello #这一步执行完毕后,去另外一个窗口(ssh窗口2),对hello这个key做incr操作,将其值变成5。完成后,继续后面的exec指令 QUEUED 127.0.0.1:6379> exec (nil) #注意,这是exec执行后返回的是nil,表示事务提交执行失败 127.0.0.1:6379> 127.0.0.1:6379> get hello "5" Redis 的数据类型? Redis 支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及 sort set(有序集合)。 string(字符串):k-v普通存储 hash(哈希):对象存储,场景:购物车 常用命令:hget hdel hlen(计算购物车总数) hincrby(增加商品件数) list(列表):队列 场景:消息队列,秒杀 常用命令 lpush lpop set(集合):求差集,交集 场景:微博粉丝关注 常用命令:sadd sdiff(差集) sinter(交集) sort set(有序集合):有序集合 场景:分数排名 常用命令:zadd zincrby(增加分数) zcard 我们实际项目中比较常用的是 string,hash 如果你是 Redis 中高级用户,还需要加上下面几种数据结构 HyperLogLog、Geo、Pub/Sub。 如果你说还玩过 Redis Module,像 BloomFilter,RedisSearch,Redis-ML,面试官得眼睛就开始发亮了。 Redis 相比 Memcached 有哪些优势? Memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类 Redis 的速度比 Memcached 快 Redis 可以持久化其数据 Redis 的持久化机制是什么?各自的优缺点? Redis提供两种持久化机制 RDB(默认) 和 AOF 机制:(配置在redis.conf) 1、RDB(Redis DataBase)持久化方式: 是指用数据集快照的方式半持久化模式)记录 redis 数据库的所有键值对,在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。 优点: - 只有一个文件 dump.rdb,方便持久化。 - 容灾性好,一个文件可以保存到安全的磁盘。 - 性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis的高性能) - 相对于数据集大时,比 AOF 的启动效率更高。 缺点: 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候 2、AOF(Append-only file)持久化方式: 是指所有的命令行记录以 redis 命令请求协议的格式完全持久化存储)保存为 aof 文件。 优点: - 数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次命令操作就记录到 aof 文件中一次。 - 通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof工具解决数据一致性问题。 - AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的 flushall)) 缺点: - AOF 文件比 RDB 文件大,且恢复速度慢。 - 数据集大的时候,比 rdb 启动效率低。 Redis 常见性能问题和解决方案: Master 最好不要写内存快照,如果 Master 写内存快照,save 命令调度 rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务 如果数据比较重要,某个 Slave 开启 AOF 备份数据,策略设置为每秒同步一次 为了主从复制的速度和连接的稳定性,Master 和 Slave 最好在同一个局域网 尽量避免在压力很大的主库上增加从库 为什么 redis 需要把所有数据放到内存中? 答 :Redis 为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以 redis 具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘 I/O 速度为严重影响 redis 的性能。在内存越来越便宜的今天,redis 将会越来越受欢迎。如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。 简单redis主从配置 1.主服务器(master)redis不做任何操作 2.从服务器(slave)redis加上 slaveof ip 端口号 配置 masterauth Rf9AtkfyQEMXl5g(主服务器redis密码) redis 过期键的删除策略? 定时删除:在设置键的过期时间的同时,创建一个定时器 timer). 让定时器在键的过期时间来临时,立即执行对键的删除操作。 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。 定期删除:每隔一段时间程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。 Redis 如何设置密码及验证密码? 设置密码:config set requirepass 123456 授权密码:auth 123456 使用过 Redis 分布式锁么,它是什么回事? 先拿 setnx 来争抢锁,抢到之后,再用 expire 给锁加一个过期时间防止锁忘记了释放。 这时候对方会告诉你说你回答得不错,然后接着问如果在 setnx 之后执行 expire之前进程意外 crash 或者要重启维护了,那会怎么样?这时候你要给予惊讶的反馈:唉,是喔,这个锁就永远得不到释放了。紧接着你需要抓一抓自己得脑袋,故作思考片刻,好像接下来的结果是你主动思考出来的,然后回答:我记得 set 指令有非常复杂的参数,这个应该是可以同时把 setnx 和expire 合成一条指令来用的! Redis连接时的connect与pconnect的区别 connect:脚本结束之后连接就释放了 pconnect:脚本结束之后连接不释放,连接保持在php-fpm进程中。 Redis 有哪些架构模式?讲讲各自的特点 参考下面的文章,作者感觉写的挺细致的 https://www.cnblogs.com/fishlynn/p/9591021.html 什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免? 缓存穿透 一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。 如何避免? 对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。 对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。 缓存雪崩 当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。 如何避免? 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。 做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀 CAP理论是什么? CAP理论
11月前 喜欢(0) 浏览(474) 评论(0)
讨论
索引 1.MyISAM和InnoDB存储引擎:只支持BTREE索引,也就是说默认使用BTREE 2.使用原则 a、对经常更新的表就避免对其进行过多的索引,对经常用于查询的字段应该创建索引, b、数据量小的表最好不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。 c、在一同值少的列上(字段上)不要建立索引,比如在学生表的"性别"字段上只有男,女两个不同值。相反的,在一个字段上不同值较多可以建立索引。 3.左模糊查询不能使用索引,比如 select * fromdoc where title like '%XX' 右模糊查询可以使用索引 InnoDB和MyISAM的区别 a.InnoDB 支持事务、行级锁, 而MyISAM都不支持 b.大量查询用MyISAM,经常更新用InnoDB c.myisam支持 FULLTEXT类型的全文索引;innodb不支持FULLTEXT类型的全文索引 d.myisam的索引以表名+.MYI文件分别保存;innodb的索引和数据一起保存在表空间里 "死锁"举例: 表Test:(ID,STATE,TIME) 主键索引:ID 非主键索引:STATE 当执行"UPDATE STATE =1011 WHERE STATE=1000" 语句的时候会锁定STATE索引,由于STATE 是非主键索引,所以Mysql还会去请求锁定ID索引 当另一个SQL语句与语句1几乎同时执行时:“UPDATE STATE=1010 WHERE ID=1” 对于语句2 Mysql会先锁定ID索引,由于语句2操作了STATE字段,所以Mysql还会请求锁定STATE索引。这时。彼此锁定着对方需要的索引,又都在等待对方释放锁定。所以出现了"死锁"的情况。 共享锁(S锁):又称为读锁,可以查看但无法修改和删除的一种数据锁。如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排它锁。获准共享锁的事务只能读数据,不能修改数据。 共享锁下其它用户可以并发读取,查询数据。但不能修改,增加,删除数据。资源共享. 排它锁(X锁):又称为写锁、独占锁,若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。这就保证了其他事务在T释放A上的锁之前不能再读取和修改A 互斥锁:在编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。 乐观锁:顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量. mysql优化 1.读写分离,分库分表 2.合理的建表,业务分割清楚,合理服务边界划分 3.通过mysql慢查询日志,分析优化sql语句,通过explain分析sql语句 4.建立合理有效的索引 数据库事务中的四大特性 ACID A:原子性(Atomicity) C:一致性(Consistency) I:隔离性(Isolation) D:持久性(Durability) 分布式事务实现会影响性能,增加程序复杂度:最好采用保证数据的最终一致性来间接实现分布式事务。 主键索引(聚簇索引)和非主键索引(二级索引)的区别? 1.主键索引叶子结点存储的是整行的数据,非主键索引叶子结点存储的是该条数据的主键的值 例如ID是主键,k是非主键子段: 如果查询语句是 select * from table where ID = 100,即主键查询的方式,则只需要搜索 ID 这棵 B+树。 如果查询语句是 select * from table where k = 1,即非主键的查询方式,则先搜索k索引树,得到ID=100,再到ID索引树搜索一次,这个过程也被称为回表。 在哪些情况会导致索引无效 1.sql语句中字段左边做了运算则索引不会生效:select * from t where c - 1 = 1000; 2.sql语句中对字段使用了函数则索引不会生效:select * from t where pow(c,2) = 1000; 3.sql语句中左模糊查询索引不会生效(... like '%aa');右模糊查询索引生效 1、脏读:一个事务可以读取另一个未提交事务的数据。需要注意的是这里针对的是数据本身,可以理解为针对单笔数据。 个人理解:事务A开启进行了查询数据,同时事务B开启,修改了其中一笔数据,但并未提交,这时事务A又进行了查询,这时就有两笔不一样的数据,然后事务B并没有结束,事务B进行了事务回滚,这样事务A就读取了事务B修改后未提交的数据。因为这里出现这种根本原因是未对数据进行提交,就进行了读取。 需进行读提交(Read Committed)就能解决。 2、不可重复读:一个事务进行读取,分别读取到了不同的数据。需要注意的是这里针对的是数据本身,可以理解为针对单笔数据,重点是对数据的修改和删除,所以对行加锁就可以解决。 个人理解:事务A对数据进行查询,这时事物B开启,对其中一笔数据进行了修改,然后进行了提交(这里进行了提交),然后事务A又对数据进行了查询,发现同一笔不同了,所以事务A读取了两笔不同的数据,两次读取同笔数据有了不同的数据。出现这种根本原因是在事务A进行读操作时,其他事务对数据进行了修改。 读提交(Read Committed)是不足以解决的,需进行可重复读(Repeatable read)就能解决。 3、幻读:一个事务进行读取,分别读取到了不同的数据。需要注意的是这里针对的是数据条数,可以理解为针对多笔数据是个数据集,重点是对数据的新增,所以对表加锁就可以解决。 个人理解:事务A对数据进行查询,这时事物B开启,对其中一笔数据进行了新增,然后进行了提交(这里进行了提交),然后事务A又对数据进行了查询,发现查询所得的结果集是不一样的。幻读针对的是多笔记录。读提交(Read Committed)是不足以解决的,需进行Serializable 序列化就能解决
11月前 喜欢(0) 浏览(453) 评论(0)
问题
有已美化过的url: http://localhost/index/default/article 如何简化URL为:http://localhost/article 首页已定义到:http://localhost/index/default/index 已默认成 :http://localhost/
1年前 喜欢(0) 浏览(416) 评论(0)
问题
两个集合没有任何关联关系,查询的时候要他们两个一起分页数据并返回给前端·,yii改怎么操作啊 谢谢
1年前 喜欢(0) 浏览(384) 评论(0)
问题
1年前 喜欢(0) 浏览(377) 评论(0)
问题
Fatal error: Class 'app\szdato\Application' not found in I:\WWW\yii\web\index.php on line 6![] 我们有个项目对接其他公司的接口,别人公司用的是YII,我们之前也没有用过yii啊,这是他们的源代码,运行后就是这样了,到底怎么回事呢? 有没有谁知道的? (/uploads/topic_20190722051529_38793.jpg)
1年前 喜欢(0) 浏览(374) 评论(0)
问题
YII2.0设置cookie的expire=0 但是该cookie在浏览器关闭了之后在打开该网页 该cookie还是存在。use browser is chorm
1年前 喜欢(0) 浏览(356) 评论(0)
博客
pid = run/php-fpm.pid pid设置,默认在安装目录中的var/run/php-fpm.pid,建议开启 error_log = log/php-fpm.log 错误日志,默认在安装目录中的var/log/php-fpm.log log_level = notice 错误级别. 可用级别为: alert(必须立即处理), error(错误情况), warning(警告情况), notice(一般重要信息), debug(调试信息). 默认: notice. emergency_restart_threshold = 60 emergency_restart_interval = 60s 表示在emergency_restart_interval所设值内出现SIGSEGV或者SIGBUS错误的php-cgi进程数如果超过 emergency_restart_threshold个,php-fpm就会优雅重启。这两个选项一般保持默认值。 process_control_timeout = 0 设置子进程接受主进程复用信号的超时时间. 可用单位: s(秒), m(分), h(小时), 或者 d(天) 默认单位: s(秒). 默认值: 0. daemonize = yes 后台执行fpm,默认值为yes,如果为了调试可以改为no。在FPM中,可以使用不同的设置来运行多个进程池。 这些设置可以针对每个进程池单独设置。 listen = 127.0.0.1:9000 fpm监听端口,即nginx中php处理的地址,一般默认值即可。可用格式为: ‘ip:port’, ‘port’, ‘/path/to/unix/socket’. 每个进程池都需要设置. listen.backlog = -1 backlog数,-1表示无限制,由操作系统决定,此行注释掉就行。backlog含义参考: http://www.3gyou.cc/?p=41 listen.allowed_clients = 127.0.0.1 允许访问FastCGI进程的IP,设置any为不限制IP,如果要设置其他主机的nginx也能访问这台FPM进程,listen处要设置成本地可被访问的IP。默认值是any。每个地址是用逗号分隔. 如果没有设置或者为空,则允许任何服务器请求连接 listen.owner = www listen.group = www listen.mode = 0666 unix socket设置选项,如果使用tcp方式访问,这里注释即可。 user = www group = www 启动进程的帐户和组 pm = dynamic #对于专用服务器,pm可以设置为static。 如何控制子进程,选项有static和dynamic。如果选择static,则由pm.max_children指定固定的子进程数。如果选择dynamic,则由下开参数决定: pm.max_children #,子进程最大数 pm.start_servers #,启动时的进程数 pm.min_spare_servers #,保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程 pm.max_spare_servers #,保证空闲进程数最大值,如果空闲进程大于此值,此进行清理 pm.max_requests = 1000 设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 ’0′ 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0. pm.status_path = /status FPM状态页面的网址. 如果没有设置, 则无法访问状态页面. 默认值: none. munin监控会使用到 ping.path = /ping FPM监控页面的ping网址. 如果没有设置, 则无法访问ping页面. 该页面用于外部检测FPM是否存活并且可以响应请求. 请注意必须以斜线开头 (/)。 ping.response = pong 用于定义ping请求的返回相应. 返回为 HTTP 200 的 text/plain 格式文本. 默认值: pong. request_terminate_timeout = 0 设置单个请求的超时中止时间. 该选项可能会对php.ini设置中的’max_execution_time’因为某些特殊原因没有中止运行的脚本有用. 设置为 ’0′ 表示 ‘Off’.当经常出现502错误时可以尝试更改此选项。 request_slowlog_timeout = 10s 当一个请求该设置的超时时间后,就会将对应的PHP调用堆栈信息完整写入到慢日志中. 设置为 ’0′ 表示 ‘Off’ slowlog = log/$pool.log.slow 慢请求的记录日志,配合request_slowlog_timeout使用 rlimit_files = 1024 设置文件打开描述符的rlimit限制. 默认值: 系统定义值默认可打开句柄是1024,可使用 ulimit -n查看,ulimit -n 2048修改。 rlimit_core = 0 设置核心rlimit最大限制值. 可用值: ‘unlimited’ 、0或者正整数. 默认值: 系统定义值. chroot = 启动时的Chroot目录. 所定义的目录需要是绝对路径. 如果没有设置, 则chroot不被使用. chdir = 设置启动目录,启动时会自动Chdir到该目录. 所定义的目录需要是绝对路径. 默认值: 当前目录,或者/目录(chroot时) catch_workers_output = yes 重定向运行过程中的stdout和stderr到主要的错误日志文件中. 如果没有设置, stdout 和 stderr 将会根据FastCGI的规则被重定向到 /dev/null . 默认值: 空.
1年前 喜欢(0) 浏览(1008) 评论(0)
博客
建议统一用 Model 封装做上传类。 功能尽量单一职责,只有一个上传功能。 如果非要添加其它字段的话,尽量添加一些简单的文字类字段。 上传后再生成一个ActiveRecord保存数据库。 这样子会避免许多麻烦。 个人见解,有好的方案大家分享分享。 以下是别人的方案,仅供参考 https://www.cnblogs.com/alanabc/p/9443391.html 第二种 解决方案 用切换场景来跳过某些检验。
1年前 喜欢(0) 浏览(1009) 评论(0)
博客
<script type="text/javascript"> var client=function(){ var engine={ //呈现引擎 trident:0, gecko:0, webkit:0, khtml:0, presto:0, ver:null //具体的版本号 }; var browser={ //浏览器 ie:0, firefox:0, safari:0, konq:0, opera:0, chrome:0, ver:null //具体的版本号 }; var system={ //操作系统 win:false, mac:false, x11:false }; var ua=navigator.userAgent; if(/AppleWebKit\/(\S+)/.test(ua)){ //匹配Webkit内核浏览器(Chrome、Safari、新Opera) engine.ver=RegExp["$1"]; engine.webkit=parseFloat(engine.ver); if(/OPR\/(\S+)/.test(ua)){ //确定是不是引用了Webkit内核的Opera browser.ver=RegExp["$1"]; browser.opera=parseFloat(browser.ver); }else if(/Chrome\/(\S+)/.test(ua)){ //确定是不是Chrome browser.ver=RegExp["$1"]; browser.chrome=parseFloat(browser.ver); }else if(/Version\/(\S+)/.test(ua)){ //确定是不是高版本(3+)的Safari browser.ver=RegExp["$1"]; browser.safari=parseFloat(browser.ver); }else{ //近似地确定低版本Safafi版本号 var SafariVersion=1; if(engine.webkit<100){ SafariVersion=1; }else if(engine.webkit<312){ SafariVersion=1.2; }else if(engine.webkit<412){ SafariVersion=1.3; }else{ SafariVersion=2; } browser.safari=browser.ver=SafariVersion; } }else if(window.opera){ //只匹配拥有Presto内核的老版本Opera 5+(12.15-) engine.ver=browser.ver=window.opera.version(); engine.presto=browser.opera=parseFloat(engine.ver); }else if(/Opera[\/\s](\S+)/.test(ua)){ //匹配不支持window.opera的Opera 5-或伪装的Opera engine.ver=browser.ver=RegExp["$1"]; engine.presto=browser.opera=parseFloat(engine.ver); }else if(/KHTML\/(\S+)/.test(ua)||/Konqueror\/([^;]+)/.test(ua)){ engine.ver=browser.ver=RegExp["$1"]; engine.khtml=browser.konq=parseFloat(engine.ver); }else if(/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)){ //判断是不是基于Gecko内核 engine.ver=RegExp["$1"]; engine.gecko=parseFloat(engine.ver); if(/Firefox\/(\S+)/.test(ua)){ //确定是不是Firefox browser.ver=RegExp["$1"]; browser.firefox=parseFloat(browser.ver); } }else if(/Trident\/([\d\.]+)/.test(ua)){ //确定是否是Trident内核的浏览器(IE8+) engine.ver=RegExp["$1"]; engine.trident=parseFloat(engine.ver); if(/rv\:([\d\.]+)/.test(ua)||/MSIE ([^;]+)/.test(ua)){ //匹配IE8-11+ browser.ver=RegExp["$1"]; browser.ie=parseFloat(browser.ver); } }else if(/MSIE ([^;]+)/.test(ua)){ //匹配IE6、IE7 browser.ver=RegExp["$1"]; browser.ie=parseFloat(browser.ver); engine.ver=browser.ie-4.0; //模拟IE6、IE7中的Trident值 engine.trident=parseFloat(engine.ver); } var p=navigator.platform; //判断操作系统 system.win=p.indexOf("Win")==0; system.mac=p.indexOf("Mac")==0; system.x11=(p.indexOf("X11")==0)||(p.indexOf("Linux")==0); if(system.win){ if(/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)){ if(RegExp["$1"]=="NT"){ system.win = ({ "5.0" : "2000", "5.1" : "XP", "6.0" : "Vista", "6.1" : "7", "6.2" : "8", "6.3" : "8.1", "10" : "10" })[RegExp["$2"]] || "NT"; }else if(RegExp["$1"]=="9x"){ system.win="ME"; }else{ system.win=RegExp["$1"]; } } } return { ua:ua, //用户浏览器Ua原文 engine:engine, //包含着用户浏览器引擎(内核)信息 browser:browser,//包括用户浏览器品牌与版本信息 system:system //用户所用操作系统及版本信息 }; }(); var iehtml = '<div class="unwelcomeie">' + '<p class="tittle">抱歉!</p>'+ '<p class="tittle">当您看到这个页面的时候,说明您使用了<b><s>IE浏览器</s></b>。</p>' + '<p>本页面运用了大量的CSS3、HTML5的新特性。因此我们决定不支持IE以及使用IE内核的国产浏览器。</p>'+ '<p>想得到我们网站最佳访问效果,我们强烈建议您升级最新版的标准浏览器。比如以下推荐的浏览器。</p>' + '<ul>' + '<li>' + '<div><img src="/cpspew/html/img/chrome.png"></div>' + '<div><a href="http://rj.baidu.com/soft/detail/14744.html">chrome下载</a></div>' + '</li>' + '<li>' + '<div><img src="/cpspew/html/img/firefox.png"></div>' + '<div><a href="http://rj.baidu.com/soft/detail/11843.html">firefox下载</a></div>' + '</li>' + '<li>' + '<div><img src="/cpspew/html/img/opera.png"></div>' + '<div><a href="http://rj.baidu.com/soft/detail/11508.html">opera下载</a></div>'+ '</li>' + '</ul>' + '<div style="clear:both;"></div>' + '</div>'; if(client.browser.ie > 1 && client.browser.ie < 10){ document.body.innerHTML = iehtml; console.log(client.browser.ie) }else{ var afigcaption = document.getElementsByTagName('figcaption'); var arrUrl = ['http://kefu.qycn.com/vclient/chat/?websiteid=120097','http://kefu.qycn.com/vclient/chat/?websiteid=120097','http://shang.qq.com/wpa/qunwpa?idkey=1bf409d240f9bc081d5d034ad290a53e53f14188a73ca8533dd44b42e41486ef','http://kefu.qycn.com/vclient/chat/?websiteid=120097']; for(var i=0;i<afigcaption.length;i++){ afigcaption[i].index = i; afigcaption[i].onclick = function(){ window.open(arrUrl[this.index]); console.log(this.index); } } } </script>
1年前 喜欢(0) 浏览(1038) 评论(0)
问题
.navbar-toggle .icon-bar { background-color: #5CB85C; } 添加后,就可以在手机端显示导航条收缩起来的三条横线了。
1年前 喜欢(0) 浏览(1257) 评论(0)
社区公告
[公告] Yii中文网为优化用户体验进行大版本升级,老版网站会维持一段时间,可以点击顶部"旧版"链接访问旧版网站。
沟通交流

:492175201(技术1群)

:183620600(技术2群)

:291010569(技术3群)

订阅号 | 更多精彩内容推送
本周推荐